美文网首页
二叉树4-二叉树展开为链表、对称二叉树、合并两个有序链表、构造二

二叉树4-二叉树展开为链表、对称二叉树、合并两个有序链表、构造二

作者: rensgf | 来源:发表于2021-04-06 22:39 被阅读0次

    14. 二叉树展开为链表

    思路:递归,将子树展开为链表。根节点右节点为左节点,左节点的右节点为右节点,左节点设为空。
    错误代码:

    class Solution {
    public:
        void flatten(TreeNode* root) {
            if(!root)
                return;
            if(root->left)
            {
                TreeNode* t1=root->left;
                TreeNode* t2=root->right;
                if(root->right)
                {
                    root->right=t1;
                    t1->right=t2;
                    root->left=nullptr;
                }
                else
                {
                    root->right=root->left;
                    root->left=nullptr;
                }
            }
            flatten(root->left);
            flatten(root->right);
        }
    };
    

    错误原因:
    递归不会写,思路不清晰。
    正确代码:

    class Solution {
    public:
        void flatten(TreeNode* root) {
            if(!root)
                return;
    //将根节点的左子树变成链表
            flatten(root->left);
     //将根节点的右子树变成链表
            flatten(root->right);
            TreeNode* t=root->right;
    //把树的右边换成左边的链表
            root->right=root->left;
    //把树的左边置空
            root->left=nullptr;
    //把右边链表接到最右边
            while(root->right)
                root=root->right;
            root->right=t;
        }
    };
    

    递归表达式要放到哪里呀

    101. 对称二叉树

    思路是:如果镜像对称,那么遍历中-左-右和中-右-左得到的结果应该一样。
    难点是如何递归?
    错误代码:

    class Solution {
    public:
        bool compare(TreeNode* root1,TreeNode* root2)
        {
            if(root1->val==root2->val)
                return true;
            else
                return false;
            return compare(root1->left,root2->right);
            return compare(root1->right,root2->left);
        }
        bool isSymmetric(TreeNode* root) {
            TreeNode* root0=root;
            if(!root)
                return true;
            return compare(root0,root); 
        }
    };
    

    错误原因:
    正确代码:
    方法一:递归法

    class Solution {
    public:
        bool compare(TreeNode* root1,TreeNode* root2)
        {
            if(!root1&&!root2)
                return true;
            if(!root1||!root2)
                return false;
            return (root1->val==root2->val)&&compare(root1->left,root2->right)&&compare(root1->right,root2->left);
        }
        bool isSymmetric(TreeNode* root) {
            if(!root)
                return true;
            return compare(root,root); 
        }
    };
    

    方法二:迭代法
    初始化时我们把根节点入队两次。每次提取两个结点并比较它们的值(队列中每两个连续的结点应该是相等的,而且它们的子树互为镜像),然后将两个结点的左右子结点按相反的顺序插入队列中。当队列为空时,或者我们检测到树不对称(即从队列中取出两个不相等的连续结点)时,该算法结束。

    class Solution {
    public:
        bool isSymmetric(TreeNode* root) {
            if(!root)
                return true;
            queue<TreeNode*> s;
            s.push(root);
            s.push(root);
            while(!s.empty())
            {
                TreeNode* p=s.front();s.pop();
                TreeNode* q=s.front();s.pop();
                if(!p&&!q)
                    continue;
                if((!p&&q)||(p&&!q)||(p->val!=q->val))
                    return false;
                s.push(p->right);
                s.push(q->left);
    
                s.push(p->left);
                s.push(q->right);
            }
            return true;
        }
    };
    

    21 . 合并两个有序链表

    错误代码:

    class Solution {
    public:
        ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
            if(!l1)
                return l2;
            if(!l2)
                return l1;
            while(l1->val>=l2->val)
            {
                ListNode* t=l2->next;
                l2->next=mergeTwoLists(l1,t);
            }
            while(l1->val<l2->val)
            {
                ListNode* t=l1->next;
                l1->next=mergeTwoLists(t,l2);
            }
            return l1;
        }
    };
    

    错误原因:不知道最后返回什么??
    正确代码:

    class Solution {
    public:
        ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
            if(!l1)
                return l2;
            if(!l2)
                return l1;
            //自顶向下
            //头结点为l2
            if(l1->val>=l2->val)
            {
                //l2在前,比较l1和l2->next
                l2->next=mergeTwoLists(l1,l2->next);
                return l2;
            }
            //头结点为l1
            else
            {
                //l1在前,比较l1->next和l2
                l1->next=mergeTwoLists(l1->next,l2);
                return l1;
            }
        }
    };
    

    105. 从前序与中序遍历序列构造二叉树

    完全没思路!根据根节点和左节点的位置顺序?如何构造?从下到上?
    思路:
    1、首先前序定位根节点;
    2、在中序遍历找出对应根节点,并分辨出左右子树;
    3、求左右子树长度,在前序遍历中找出子树;
    4、递归。
    逐个在前序找。然后中序找出索引。把那个索引的值的左边数组看为左子树,右边数组为右子树。

    class Solution {
    public:
        int indexit(vector<int>& vec,int p)
        {
            vector<int>::iterator it=find(vec.begin(),vec.end(),p);
            int dis=distance(vec.begin(),it);
            return dis;
        }
        TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
            if(preorder.empty())
                return nullptr;
            TreeNode *newTree= new TreeNode(preorder[0]);//初始化根节点
            int loc=indexit(inorder,preorder[0]);//查找根节点在中序遍历中的位置
            int l1=loc,l2=preorder.size()-loc-1;//左子树、右子树的长度
            vector<int>leftTree(inorder.begin(),inorder.begin()+l1);//左子树结点中序
            vector<int>rightTree(inorder.end()-l2,inorder.end());//右子树结点中序
    
            vector<int>preleftTree(preorder.begin()+1,preorder.begin()+l1+1);//左子树前序
            vector<int>prerightTree(preorder.end()-l2,preorder.end());//右子树前序
    
            newTree->left=buildTree(preleftTree, leftTree);//递归子树
            newTree->right=buildTree(prerightTree, rightTree);
            return newTree;
        }
    };
    

    相关文章

      网友评论

          本文标题:二叉树4-二叉树展开为链表、对称二叉树、合并两个有序链表、构造二

          本文链接:https://www.haomeiwen.com/subject/eyfqkltx.html