0
点赞
收藏
分享

微信扫一扫

二叉树OJ训练

古得曼_63b6 2022-04-04 阅读 28

二叉树OJ训练

1. 二叉树

1.1 LeetCode第965题—单值二叉树

LeetCode题目链接:https://leetcode-cn.com/problems/univalued-binary-tree/
在这里插入图片描述

//分解为当前树 和左子树 右子树的子问题然后进行递归
bool isUnivalTree(struct TreeNode* root){
    if(root == NULL)
        return true;

    //检查当前树
    if(root->left && root->val != root->left->val)
        return false;
    if(root->right && root->val != root->right->val)
        return false;
        
    return isUnivalTree(root->left) && isUnivalTree(root->right);
}

1.2 LeetCode第104题—二叉树的最大深度

LeetCode题目链接:https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/
在这里插入图片描述

int maxDepth(struct TreeNode* root){
    if(root == NULL)
        return 0;
        //为的就是消除代码冗余
    int leftDepth = maxDepth(root->left);
    int rightDepth = maxDepth(root->right);

//求出左右子树较大的哪一个
    return leftDepth > rightDepth? leftDepth+1 :rightDepth+1;
}

1.4 LeetCode第111题—二叉树的最小深度

LeetCode题目链接:https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/
在这里插入图片描述
层序的方法:

class Solution {
public:
    //是从根到叶子节点
    int minDepth(TreeNode *root) {
        if (root == nullptr) {
            return 0;
        }
        queue<pair<TreeNode *, int> > que;
        que.emplace(root, 1);
        while (!que.empty()) {
            TreeNode *node = que.front().first;
            int depth = que.front().second;
            que.pop();
            if (node->left == nullptr && node->right == nullptr) {
                return depth;
            }
            if (node->left != nullptr) {
                que.emplace(node->left, depth + 1);
            }
            if (node->right != nullptr) {
                que.emplace(node->right, depth + 1);
            }
        }
        return 0;
    }
};

1.5 LeetCode第100题—相同的树

LeetCode题目链接:https://leetcode-cn.com/problems/same-tree/
在这里插入图片描述

//把每一种情况都考虑到
bool isSameTree(struct TreeNode* p, struct TreeNode* q){
    if(p == NULL && q == NULL)
        return true;
    
    //结构不同
    if(p != NULL && q == NULL)
        return false;
    if(p == NULL && q != NULL)
        return false;
    
    //走到这里的时候就可以确定此时p和q都是不为空的,再来判断他们的值是否相同
    if(p->val != q->val) //此时==并不能判断出来结果,不能说他们一开始给的两个结点相同就直接返回true
        return false;

    
    
    return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
 
}

1.6 LeetCode第572题—另一棵树的子树

在这里插入图片描述

class Solution {
public:
    bool isSametree(TreeNode* p,TreeNode* q)
    {
        if(p == nullptr && q == nullptr)
            return true;
        if(p == nullptr || q == nullptr)
            return false;
        if(p->val != q->val)
            return false;
        return isSametree(p->left,q->left) && isSametree(p->right,q->right);
    }
    bool isSubtree(TreeNode* root, TreeNode* subRoot) {
        if(root == nullptr && subRoot != nullptr)
            return false;
        if(isSametree(root,subRoot))
            return true;
        return isSubtree(root->left,subRoot) || isSubtree(root->right,subRoot);
    }
};

1.7 剑指offer27题—二叉树的镜像

LeetCode题目链接:https://leetcode-cn.com/problems/er-cha-shu-de-jing-xiang-lcof/
在这里插入图片描述

class Solution {
public:
    TreeNode* mirrorTree(TreeNode* root) {
        if(root == nullptr)
            return nullptr;
        TreeNode* tmp = root->left;
        root->left = root->right;
        root->right = tmp;
        mirrorTree(root->left);
        mirrorTree(root->right);
        return root;
    }
};

1.8 剑指offer26题—树的子结构(重点)

LeetCode题目链接:https://leetcode-cn.com/problems/shu-de-zi-jie-gou-lcof/
在这里插入图片描述
子树和子结构是两种不一样的题。

class Solution {
public:
    bool isSame(TreeNode* p,TreeNode* q)
    {
        //因为对于这个子结构,肯定是q先遍历完
        if(q == nullptr)
            return true;
        if(p == nullptr || p->val != q->val)
            return false;
        return isSame(p->left,q->left) && isSame(p->right,q->right);
    }
    bool isSubStructure(TreeNode* A, TreeNode* B) {
        //因为题目规定空树不算任意一个树的子结构
        if(A == nullptr || B == nullptr)
            return false;
        //B还可能是A左子树的子结构或者或是A右子树的子结构
        if(isSame(A,B))
            return true;
        return isSubStructure(A->left,B) || isSubStructure(A->right,B);
    }
};

1.9 剑指offer28题—对称的二叉树

LeetCode题目链接:https://leetcode-cn.com/problems/dui-cheng-de-er-cha-shu-lcof/在这里插入图片描述

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

1.10 LeetCode第114题—二叉树展开为链表

LeetCode题目链接:https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list/
在这里插入图片描述

class Solution {
public:
    void prevorder(TreeNode* root,vector<TreeNode*>& v)
    {
        if(root == nullptr)
            return;
        v.push_back(root);
        prevorder(root->left,v);
        prevorder(root->right,v);
    }
    void flatten(TreeNode* root) {
        vector<TreeNode*> v;
        //我们前序就得到了数组
        prevorder(root,v);
        //每一个节点的左节点始终为nullptr,右节点要指向下一个节点
        for(int i = 1;i<v.size();++i)
        {
            TreeNode* prev = v[i-1],*cur = v[i];
            prev->left = nullptr;
            prev->right = cur;
        }
    }
};

1.11 剑指offer68题—二叉树的最近公共祖先

LeetCode题目链接:https://leetcode-cn.com/problems/er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof/
在这里插入图片描述

class Solution {
public:
    bool FindPath(TreeNode* root,TreeNode* x,stack<TreeNode*>& Path)
    {
        if(root == nullptr)
            return false;
        Path.push(root);
        //说明已经找到那个点了
        if(root == x)
            return true;
        //你的FindPath本身就是一个bool值返回的函数呀
        if(FindPath(root->left,x,Path))
            return true;
        if(FindPath(root->right,x,Path))
            return true;
        Path.pop();
        return false;
    }
    //这道题在我眼里还是挺难的,这里反手就是一个简单,无奈
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        //简单点说就是找到p的路径,找到q的路径,这样可以很大程度上降低时间复杂度
        stack<TreeNode*> pPath;
        stack<TreeNode*> qPath;
        FindPath(root,p,pPath);
        FindPath(root,q,qPath);
        //我们就得到了两个节点的路径
        while(pPath.size() > qPath.size())
            pPath.pop();
        while(pPath.size() < qPath.size())
            qPath.pop();
        //此时他们两个路径就是相同的了,然我们要找到相同的点
        while(pPath.top() != qPath.top())
        {
            pPath.pop();
            qPath.pop();
        }
        return pPath.top();
    }
};

1.12 LeetCode第114题—根据二叉树创建字符串

LeetCode题目链接:https://leetcode-cn.com/problems/construct-string-from-binary-tree/
在这里插入图片描述

题目分析:左子树的括号是一定不能够删除的,但是右子树的括号是可以删除的,还有一种情况就是当前节点的左右子树都为空的时候,直接返回那个拼接的字符串递归回上一层就好。

class Solution {
public:
    //其实对于这道题最难的是分析示例,根据前序遍历,只要遇见左子树之前就加一个括号,在左子树结束就加一个收括号
    string tree2str(TreeNode* root) {
        //通过示例分析,可以看出来左树的括号一定不能够省略,但是右树的括号在一定条件下是可以省略的
        string s;
        if(root == nullptr)
            return s;
        s += to_string(root->val);
        if(root->left == nullptr && root->right == nullptr)
            return s;

        s += "(";
        s += tree2str(root->left);
        s += ")";

        if(root->right)
        {
            s += "(";
            s += tree2str(root->right);
            s += ")";
        }
        return s;
    }
};

2. 二叉搜索树

2.1 剑指offer55题—平衡二叉树(重要)

LeetCode题目链接:https://leetcode-cn.com/problems/ping-heng-er-cha-shu-lcof/
在这里插入图片描述
要利用到求树的深度这个子函数,但是你算出来根节点的左右子树的高度差不能超过1,但是还要验证左子树也符合平衡搜索树,右子树也符合平衡搜索树的条件。

class Solution {
public:
    int TreeDepth(TreeNode* root)
    {
        if(root == nullptr)
            return 0;
        int leftDepth = TreeDepth(root->left);
        int rightDepth = TreeDepth(root->right);
        return leftDepth > rightDepth? 1+leftDepth:1+rightDepth;
    }
    bool isBalanced(TreeNode* root) {
        if(root == nullptr)
            return true;
        int gap = TreeDepth(root->left) - TreeDepth(root->right);
        //我无法判断当前树是否就可以直接的满足条件,但是我可以判断如果当前树就无法满足,那么直接就应该返回false
        if(abs(gap) > 1)
            return false;
        return isBalanced(root->left) && isBalanced(root->right);    
    }
};

2.2 LeetCode第235题—二叉搜索树的最近公共祖先

LeetCode题目链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree/
在这里插入图片描述
要充分利用起来二叉搜索树的性质才可以。

class Solution {
public:
    //当然这道题可以使用二叉树的普通方法来做题
    //但是这道题本应该充分利用到二叉搜索树的性质,这样做题才是正确的思路
    //这样这道题就充分利用到了二叉搜索树的性质
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        TreeNode* ancestor = root;
        while(true)
        {
            if(p->val < ancestor->val && q->val < ancestor->val)
                ancestor = ancestor->left;
            else if(p->val > ancestor->val && q->val > ancestor->val)
                ancestor = ancestor->right;
            else 
                //这种情况就是其中一个节点就是自己的祖先
                break;
        }
        return ancestor;
    }
};

2.2 剑指offer54题—二叉树搜索树的第K大节点

LeetCode题目链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-di-kda-jie-dian-lcof/
在这里插入图片描述

class Solution {
public:
    //二叉搜索树中序遍历的本身就是有序的
    void inorder(TreeNode* cur,vector<int>& v)
    {
        if(cur == nullptr)
            return;
        inorder(cur->left,v);
        v.push_back(cur->val);
        inorder(cur->right,v);
    }
    int kthLargest(TreeNode* root, int k) {
        if(root == nullptr)
            return 0;
        vector<int> v;
        inorder(root,v);
        //此时调用完这个中序遍历之后这个v就是我们想要的
        reverse(v.begin(),v.end());
        return v[k-1];
    }
};

2.3 剑指offer36题—二叉树搜索树与双向链表(重点)

LeetCode题目链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/submissions/
在这里插入图片描述

class Solution {
public:
    void _treeToDoublyList(Node* cur,Node*& prev)
    {
        if(cur == nullptr)
            return;
        _treeToDoublyList(cur->left,prev);
        cur->left = prev;
        if(prev)
        {
            prev->right = cur;
        }
        prev = cur;
        _treeToDoublyList(cur->right,prev);
    }
    Node* treeToDoublyList(Node* root) {
        if(root == nullptr)
            return nullptr;
        Node* prev = nullptr;
        _treeToDoublyList(root,prev);
        Node* head = root;
        while(head->left)
        {
            head = head->left;
        }
        Node* tail = root;
        while(tail->right)
        {
            tail = tail->right;
        }
        head->left = tail;
        tail->right = head;
        return head;
    }
};

2.4 LeetCode第538题—把二叉搜索树转换为累加树

LeetCode题目链接:https://leetcode-cn.com/problems/convert-bst-to-greater-tree/
在这里插入图片描述
仔细分析这个图,你就会发现,他的遍历顺序其实是右根左,调整一下顺序就好了。

class Solution {
public:
    //仔细感觉就会发现,对于二叉搜索树来说,正常写中序遍历是升序,但是如果左右子树相交换,那么就会是倒叙的情况
    //然后你仔细看这个图,就能明白啥意思了
    void postOrder(TreeNode* root,int& sum)
    {
        if(root == nullptr)
            return;
        postOrder(root->right,sum);
        sum += root->val;
        root->val = sum;
        postOrder(root->left,sum);
    }
    TreeNode* convertBST(TreeNode* root) {
        int sum = 0;
        postOrder(root,sum);
        return root;
    }
};

2.5 LeetCode第98题—验证二叉搜索树

LeetCode题目链接:https://leetcode-cn.com/problems/validate-binary-search-tree/
在这里插入图片描述
解题思路:这道题会很容易犯一个很致命的错误,那就是简单的使用中序然后我们判断一下是否这个中序满足有序,但是这种做法是错误的,从测试用例其实也能够感觉出来。所以这道题我们究竟应该怎么做呢?使用中序遍历,看一下是否满足下一个节点处理的值大于上一个节点的值。

class Solution {
public:
    //对于验证二叉搜索树,我们不能够简单的通过中序遍历,然后看是否他是一个有序的数组,因为这样是不对的,
    //比如说例子二的测试用例
    //二叉搜索树需要满足的是左子树节点都小于中间节点,右子树的值都大于中间节点
    //我们需要验证左树是否满足二叉搜索树,还需要验证右树是否满足二叉搜索树,还需要验证根节点
    long long min = LONG_MIN;
    bool isValidBST(TreeNode* root) {
        if(root == nullptr)
            return true;
        bool left = isValidBST(root->left);
        if(min < root->val)
            min = root->val;
        else 
            return false;
        bool right = isValidBST(root->right);
        return left && right;
    }
};

2.6 LeetCode第99题—恢复二叉搜索树

LeetCode题目链接:https://leetcode-cn.com/problems/recover-binary-search-tree/
在这里插入图片描述
解题思路:这道题的解题方法提供了一个很好的方式,首先我们知道二叉搜索树的中序遍历是一个有序的,但是现在题目所给的树的顺序中序遍历肯定是错的,所以,我们要修正我们想要的结果,先得到正确的中序的顺序,然后我们重新去拿着这个有序数组去修改原来树错误节点的结果

class Solution {
public:    
    void recoverTree(TreeNode* root) {
        vector<int> result;
        inOrder(root,result); //中序遍历得到错误结果
        sort(result.begin(),result.end()); //重新排序得到正确结果
        //我继续根据中序,在把树给回复回来
        recover(root,result); //对比原来的结点,一个个重新恢复
    }

    //中序遍历,保存数组
    void inOrder(TreeNode* root,vector<int>& vecResult){
        if(root == nullptr){
            return;
        }
        inOrder(root->left,vecResult);
        vecResult.push_back(root->val);
        inOrder(root->right,vecResult);
    }

    //逐个对比修改正确结果
    //如何保证递归的过程中,始终能找到数组中的那个下标
    //这道题的解题思路其实很好的提供了一种方法
    void recover(TreeNode* root,vector<int>& rec){
        if(root ==nullptr){
            return;
        }
        recover(root->left,rec);
        if(root->val == rec[0]){
            rec.erase(rec.begin());
        }else{
            root->val = rec[0];
            rec.erase(rec.begin());
        };
        recover(root->right,rec);
    }
};

2.7 剑指offer33题—二叉树搜索树的后续遍历序列(重点)

LeetCode题目链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-hou-xu-bian-li-xu-lie-lcof/
在这里插入图片描述

class Solution {
public:
   //首先对于不适合递归的函数是需要自己写一个的,首先我们可以得到一段范围区间[i,j]
    //题目已经说了是二叉搜索树,那么他的左子树都满足 < 根节点值
    //右子树都满足 > 根节点值,并且遍历的顺序是 左 右 根
    bool IsPosterorder(vector<int>& postorder,int left,int right)
    {
        //递归这里一定还要有一个返回条件
        if(left >= right)
            return true;
        int root = postorder[right];//就得到了根节点
        //然后遍历找到第一个大于根节点的地方
        int i = left;
        while(postorder[i] < root)
        {
            i++;
        }
        //到这里的时候刚好i所呆的位置,刚好也是右子树起始的区间下标
        //此时就得到了左子树和右子树的区间,然后再分别验证
        //[left,i-1]  [i,right-1]
        int j = i;
        while(postorder[j] > root)
        {
            j++;
        }
        //此时j停下的位置应该就是根节点的位置
        //解题的关键就在于是否能够充分的发挥二叉搜索树的特征和定义
        //就是检查当前树,左子树,右子树,是否都满足二叉搜索树的定义
        return j == right && IsPosterorder(postorder,left,i-1) && IsPosterorder(postorder,i,right-1);
    }
    bool verifyPostorder(vector<int>& postorder) {
        if(postorder.size() == 0)
            return true;
        return IsPosterorder(postorder,0,postorder.size()-1);
    }
};

3. 重建二叉树系列

其实你会发现,这几道题都是使用已知的前序用来构建二叉树,当有中序和后续的时候,他们的存在就是为了能够更好的知道左子树和右子树的具体区间。

3.1 剑指offer7题—重建二叉树(重点)

此道题和LeetCode第105题一样
在这里插入图片描述
解题思路:

class Solution {
public:
    TreeNode* _buildTree(vector<int>& preorder, vector<int>& inorder,int prevbegin,int prevend,int inbegin,int inend)
    {
        if(prevbegin > prevend || inbegin > inend)
            return nullptr;
        TreeNode* root = new TreeNode(preorder[prevbegin]);
        int rooti = inbegin;
        while(rooti <= inend && inorder[rooti] != preorder[prevbegin])
            rooti++;
        int length = rooti - inbegin;
        root->left = _buildTree(preorder,inorder,prevbegin+1,prevbegin+length,inbegin,rooti-1);    
        root->right = _buildTree(preorder,inorder,prevbegin+length+1,prevend,rooti+1,inend);
        return root;     
    }

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        return _buildTree(preorder,inorder,0,preorder.size()-1,0,inorder.size()-1);
    }
};

3.2 LeetCode第106题—中序与后续序列构建二叉树

LeetCode题目链接:https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/
在这里插入图片描述

class Solution {
public:
    //使用后续来构建这棵树
    TreeNode* _bulidTree(vector<int>& inorder, vector<int>& postorder,int inbegin,int inend,int postbegin,int postend)
    {
        if(postbegin > postend)
            return nullptr;
        TreeNode* root = new TreeNode(postorder[postend]);
        int rooti = inbegin;
        while(rooti<=inend && inorder[rooti] != postorder[postend])
            rooti++;
        int length = rooti-inbegin;
        root->left = _bulidTree(inorder,postorder,inbegin,rooti-1,postbegin,postbegin+length-1);
        root->right = _bulidTree(inorder,postorder,rooti+1,inend,postbegin+length,postend-1);
        return root;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        return _bulidTree(inorder,postorder,0,inorder.size()-1,0,postorder.size()-1);
    }
};

3.3 LeetCode第889题—前序和后续遍历构建二叉树

LeetCode题目链接:https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-postorder-traversal/
在这里插入图片描述
解题思路:这道题和上面几道题的一个不同之处,就是很有可能会出现数组越界的问题,所以为了避免数组越界的问题,我们应该在这里加一个判断

class Solution {
public:
    //后续确定范围以及左右子树中节点的个数
    TreeNode* buildTree(vector<int>& preorder, vector<int>& postorder,int prevbegin,int prevend,int postbegin,int postend)
    {
        if(prevbegin > prevend)
            return nullptr;
        TreeNode* root = new TreeNode(preorder[prevbegin]);
        //这里为啥要做一个这样的判断,是因为后面有可能会数组越界,因为postorder[rooti] != preorder[prevbegin+1]这段代码
        if(prevbegin == prevend)
            return root;
        int nextHeadval = preorder[prevbegin+1];
        int rooti = postbegin;
        while(rooti <= postend && postorder[rooti] != nextHeadval)
            rooti++;
        int length = rooti-postbegin+1; 
        root->left = buildTree(preorder,postorder,prevbegin+1,prevbegin+length,postbegin,rooti);
        root->right = buildTree(preorder,postorder,prevbegin+length+1,prevend,rooti+1,postend-1);
        return root;
    }
    TreeNode* constructFromPrePost(vector<int>& preorder, vector<int>& postorder) {
        return buildTree(preorder,postorder,0,preorder.size()-1,0,postorder.size()-1);
    }
};

3.4 LeetCode第654题—最大二叉树

LeetCode题目链接:https://leetcode-cn.com/problems/maximum-binary-tree/
在这里插入图片描述

class Solution {
public:
    int FindMaxIndex(vector<int>& nums,int left,int right)
    {
        //我就想求出这段区间中的最大值
        int MaxValue = INT_MIN,Maxindex = -1;
        for(int i = left;i<=right;++i)
        {
            if(MaxValue < nums[i])
            {
                MaxValue = nums[i];
                Maxindex = i;
            }
        }
        return Maxindex;
    }
    TreeNode* MaxTree(vector<int>& nums,int left,int right)
    {
        if(left > right)
            return nullptr;
        int index = FindMaxIndex(nums,left,right);
        TreeNode* root = new TreeNode(nums[index]);
        //这里实在递归,怎么能写0呢?
        root->left = MaxTree(nums,left,index-1);
        root->right = MaxTree(nums,index+1,right);
        return root;
    }
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        int n = nums.size();
        if(n == 0)
            return nullptr;
        //首先就是找到数组中,最大值和其对应的下标,然后就是做切分
        return MaxTree(nums,0,n-1);
    }
};

3.5 LeetCode108题—将有序数组转换为二叉搜索树

LeetCode题目链接:https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree/
在这里插入图片描述

class Solution {
public:
    TreeNode* constructBST(vector<int>& nums,int left,int right)
    {
        if(left > right)
            return nullptr;
        int mid = (left + right) / 2;
        TreeNode* root = new TreeNode(nums[mid]);
        root->left = constructBST(nums,left,mid-1);
        root->right = constructBST(nums,mid+1,right);
        return root;
    }
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        //既然是有序数组那么一定是二叉搜索树的中序遍历
        //为了达到高度平衡我们应该选择以中间节点作为二叉树的根然后左右开始构建二叉树
        return constructBST(nums,0,nums.size()-1);
    }
};

3.6 LeetCode109题—将有序链表转换为二叉搜索树

LeetCode题目链接:https://leetcode-cn.com/problems/convert-sorted-list-to-binary-search-tree/
在这里插入图片描述
这道题其实可以使用108题的解法思路,比如先将有序链表转换为有序数组,然后我们使用相同的方法进行构建。但是最好还是使用链表的方式来解决。

class Solution {
public:
    //这道题能不能先将有序链表转换为有序数组,然后进行其他的操作
    //答案应该也是对的,但是我们想要以有序链表的方式做这道题
    TreeNode* sortedListToBST(ListNode* head) {
        //如果没有这一句我们会发现在递归过程中无法返回
        if(head == nullptr)
            return nullptr;
        ListNode* slow = head,*fast = head;
        ListNode* pre = nullptr;
        //对于奇数个节点和偶数个节点来说,判断停止的条件是不一样的
        while(fast && fast->next)
        {
            //每次在slow走之前,我们先让他被保留一份
            pre = slow;
            slow = slow->next;
            fast = fast->next->next;
        }
        //当我们犹豫不知道该如何返回的时候我们就应该思考,是否我们不需要将该函数分离出去
        TreeNode* root = new TreeNode(slow->val);
        if(pre)
        {
            //将其从链表中分割开来
            pre->next = nullptr;
            root->left = sortedListToBST(head);
        }
        root->right =sortedListToBST(slow->next);
        return root;
    }
};

4. 二叉树非递归前中后序遍历

文章链接:https://blog.csdn.net/MEANSWER/article/details/117151815

5. 二叉树的层序遍历

5.1 二叉树的分层遍历I

5.2 二叉树的分层遍历II

文章链接:https://blog.csdn.net/MEANSWER/article/details/117108788

5.3 LeetCode第103题—二叉树的锯齿形层序遍历

LeetCode题目链接:https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal/
在这里插入图片描述
使用deque会比较好,因为既可以头插还可以尾插

 //在这题中为啥使用deque是需要好好思考的,就是看重了他既能够尾插也能够头删
class Solution {
public:
    //你觉得这个和正常的层序遍历之间有什么不一样吗?
    //不需要那么麻烦就是简单的一个标志位
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        vector<vector<int>> vv;
        if(!root)
            return vv;
        queue<TreeNode*> q;
        q.push(root);
        bool IsEvenLevel = true;
        while(!q.empty())
        {
            int num = q.size();
            deque<int> dq;  //仔细想这里为什么要用deque,因为这个可以很方便的进行头插和头删
            while(num--)
            {
                TreeNode* node = q.front();
                q.pop();
                if(IsEvenLevel)
                {
                    dq.push_back(node->val);
                }
                else
                {
                    dq.push_front(node->val);
                }
                if(node->left)
                    q.push(node->left);
                if(node->right)
                    q.push(node->right);
            }
            vector<int> v(dq.begin(),dq.end());
            vv.push_back(v);
            IsEvenLevel = !IsEvenLevel;
        }
        return vv;
    }
};

5.4 LeetCode第404题—左叶子之和

LeetCode题目链接:<>
在这里插入图片描述
这道题我感觉使用层序遍历的方法其实更加的清晰明了

class Solution {
public:
    //这道题我们使用层序的方法好像更容易去理解
    int sumOfLeftLeaves(TreeNode* root) {
        if(root == nullptr)
            return 0;
        queue<TreeNode*> q;
        q.push(root);
        int sum = 0;
        while(!q.empty())
        {
            int LevelSize = q.size();
            while(LevelSize--)
            {
                TreeNode* top = q.front();
                q.pop();
                //左边我们要特殊处理,右边我们应该正常处理就可以
                if(top->left)
                {
                    if(top->left->left == nullptr && top->left->right == nullptr)
                        sum += top->left->val;
                    else
                        q.push(top->left);
                }
                if(top->right)
                    q.push(top->right);
            }
        }
        return sum;
    }
};

5.5 LeetCode第199题—二叉树的右视图

LeetCode题目链接:https://leetcode-cn.com/problems/binary-tree-right-side-view/
在这里插入图片描述
题解思路:只需要将每一层的最后一个插入到我们定义的数组中就可以,找到从右边看到的所有节点值了。

class Solution {
public:
    //其实这道题完全可以使用层序遍历来完成
    vector<int> rightSideView(TreeNode* root) {
        if(root == nullptr)
            return {};
        vector<int> v;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty())
        {
            int LevelSize = q.size();
            for(int i = 0;i<LevelSize;++i)
            {
                TreeNode* cur = q.front();
                q.pop();
                if(cur->left)
                    q.push(cur->left);
                if(cur->right)
                    q.push(cur->right);
                //表示为这一层的最后一个
                if(i == LevelSize-1)
                    v.push_back(cur->val);
            }
        }
        return v;
    }
};
举报

相关推荐

0 条评论