Leetcode刷题——树篇6

文章目录

  • 6、树(中等篇2)
    • 6.1、94. 二叉树的中序遍历
    • 6.2、1261. 在受污染的二叉树中查找元素
    • 6.3、230. 二叉搜索树中第K小的元素
    • 6.4、1325. 删除给定值的叶子节点
    • 6.5、513. 找树左下角的值
    • 6.6、114. 二叉树展开为链表
    • 6.7、222. 完全二叉树的节点个数
    • 6.8、106. 从中序与后序遍历序列构造二叉树
    • 6.9、1104. 二叉树寻路
    • 6.10、979. 在二叉树中分配硬币

6、树(中等篇2)

6.1、94. 二叉树的中序遍历

给定一个二叉树,返回它的中序 遍历。

示例:

输入: [1,null,2,3]
在这里插入图片描述
输出: [1,3,2]
进阶: 递归算法很简单,你可以通过迭代算法完成吗?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析:中序遍历递归实现很简单,下面题解代码主要是非递归的方式。

题解代码(C++):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root==NULL) return res;
        stack<TreeNode*> s;
        TreeNode* cur = root;
        while(cur!=NULL||!s.empty()){
            while(cur!=NULL){
                s.push(cur);
                cur = cur->left;
            }
            if(!s.empty()){
                cur = s.top();s.pop();
                res.push_back(cur->val);
                cur = cur->right;
            }
        }
        return res;
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        if(root==null) return res;
        Stack<TreeNode> s = new Stack<TreeNode>();
        TreeNode cur = root;
        while(cur!=null || !s.isEmpty()){
            while(cur!=null){
                s.push(cur);
                cur =cur.left;
            }
            if(!s.isEmpty()){
                cur = s.pop();
                res.add(cur.val);
                cur = cur.right;
            }
        }
        return res;
    }
}

题解代码(Python):

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        res = []
        if root is None:
            return res
        s = []
        cur = root
        while cur is not None or len(s)>0:
            while cur is not None:
                s.append(cur)
                cur = cur.left
            if len(s)>0:
                cur = s.pop()
                res.append(cur.val)
                cur = cur.right
                
        return res

6.2、1261. 在受污染的二叉树中查找元素

给出一个满足下述规则的二叉树:

root.val == 0
如果 treeNode.val == x 且 treeNode.left != null,那么treeNode.left.val == 2 * x + 1
如果 treeNode.val == x 且 treeNode.right != null,那么 treeNode.right.val == 2 * x + 2 现在这个二叉树受到「污染」,所有的treeNode.val 都变成了 -1。

请你先还原二叉树,然后实现 FindElements 类:

FindElements(TreeNode* root) 用受污染的二叉树初始化对象,你需要先把它还原。 bool find(int
target) 判断目标值 target 是否存在于还原后的二叉树中并返回结果。

示例 1: Leetcode刷题——树篇6_第1张图片

输入: [“FindElements”,“find”,“find”]
[[[-1,null,-1]],[1],[2]]
输出:[null,false,true]
解释: FindElements findElements = newFindElements([-1,null,-1]);
findElements.find(1); // return False
findElements.find(2); // return True
示例 2:
Leetcode刷题——树篇6_第2张图片

输入: [“FindElements”,“find”,“find”,“find”]
[[[-1,-1,-1,-1,-1]],[1],[3],[5]]
输出: [null,true,true,false]
解释:
FindElements findElements = new FindElements([-1,-1,-1,-1,-1]);
findElements.find(1); // return True
findElements.find(3); // return
True findElements.find(5); // return False
示例 3:

Leetcode刷题——树篇6_第3张图片

输入: [“FindElements”,“find”,“find”,“find”,“find”]
[[[-1,null,-1,-1,null,-1]],[2],[3],[4],[5]]
输出:
[null,true,false,false,true]
解释: FindElements findElements = new FindElements([-1,null,-1,-1,null,-1]); findElements.find(2); // returnTrue
findElements.find(3); // return False
findElements.find(4); //return False
findElements.find(5); // return True

提示:

TreeNode.val == -1 二叉树的高度不超过 20 节点的总数在 [1, 104] 之间 调用 find() 的总次数在 [1, 104] 之间 0 <= target <= 106

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-elements-in-a-contaminated-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析:首先是要修复受污染的树,本质上修改结点的值,首先是把根节点值置为0,然后递归修复左右子树,如果左右孩子存在,则根据传入的参数修改值,如果左右孩子不存在,则返回。

修复完树之后是查找,在修复的时候就把新值加入到set集合中,调用find()函数时可以使用set集合查找的方法即可。

题解代码(C++):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class FindElements {
public:
    set<int> myset;
    void dfs(TreeNode* root,int val){
        if(root==NULL) return;
        root->val=val;
        myset.insert(root->val);
        dfs(root->left,2*root->val+1);
        dfs(root->right,2*root->val+2);
    }

    FindElements(TreeNode* root) {
        root->val = 0;
        dfs(root->left,2*root->val+1);
        dfs(root->right,2*root->val+2);
    }
    
    bool find(int target) {
        return myset.find(target)!=myset.end();
    }
};

/**
 * Your FindElements object will be instantiated and called as such:
 * FindElements* obj = new FindElements(root);
 * bool param_1 = obj->find(target);
 */

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class FindElements {
    Set<Integer> myset;
    public void dfs(TreeNode root,int val){
        if(root==null) return;
        root.val = val;
        myset.add(val);
        dfs(root.left,2*val+1);
        dfs(root.right,2*val+2);
    }
    public FindElements(TreeNode root) {
        this.myset = new HashSet<>();
        root.val = 0;
        dfs(root.left,1);
        dfs(root.right,2);
    }
    
    public boolean find(int target) {
        return this.myset.contains(target);
    }
}

/**
 * Your FindElements object will be instantiated and called as such:
 * FindElements obj = new FindElements(root);
 * boolean param_1 = obj.find(target);
 */

题解代码(Python):

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class FindElements:
    def __init__(self, root: TreeNode):
        self.myset = set()
        root.val=0
        self.dfs(root.left,1)
        self.dfs(root.right,2)

    def dfs(self,root:TreeNode,val:int):
        if root is None:
            return None
        root.val=val
        self.myset.add(val)
        self.dfs(root.left,2*val+1)
        self.dfs(root.right,2*val+2)

    def find(self, target: int) -> bool:
        return target in self.myset

        


# Your FindElements object will be instantiated and called as such:
# obj = FindElements(root)
# param_1 = obj.find(target)

6.3、230. 二叉搜索树中第K小的元素

给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素。
说明: 你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数。
示例 1:
输入: root = [3,1,4,null,2], k = 1

   3
  / \
 1   4
  \    
   2   

输出: 1
示例2:
输入: root = [5,3,6,2,4,null,null,1], k = 3

      5
     / \
    3   6
   / \    
  2   4   
 /  
1 

输出: 3

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/kth-smallest-element-in-a-bst
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析:二叉搜索树的中序遍历是升序的结果,找到第k个访问的结点值即可,可以递归遍历,也可以非递归遍历。

题解代码(C++):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int count,res;
    void dfs(TreeNode* root,int &k){
        if(root==NULL||this->count==k) return;
        dfs(root->left,k);
        this->count++;
        if(this->count==k) {this->res = root->val;k--;return;}
        dfs(root->right,k);

    }
    int kthSmallest(TreeNode* root, int k) {
        this->count=0;
        dfs(root,k);
        return this->res;
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int count =0;
    int res;
    public void dfs(TreeNode root,int k){
        if(root==null || this.count==k) return;
        dfs(root.left,k);
        this.count++;
        if(this.count==k) {this.res = root.val;return;}
        dfs(root.right,k);
    }
    public int kthSmallest(TreeNode root, int k) {
        this.count = 0;
        dfs(root,k);
        return this.res;
    }
}

题解代码(Python):

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def kthSmallest(self, root: TreeNode, k: int) -> int:
        res,count = 0,0
        s = []
        cur = root
        while cur is not None or len(s)>0:
            while cur is not None:
                s.append(cur)
                cur = cur.left
            if len(s)>0:
                cur = s.pop()
                count+=1
                if count ==k:
                    res = cur.val
                cur = cur.right
        return res

6.4、1325. 删除给定值的叶子节点

给你一棵以 root 为根的二叉树和一个整数 target ,请你删除所有值为 target 的 叶子节点 。

注意,一旦删除值为 target 的叶子节点,它的父节点就可能变成叶子节点;如果新叶子节点的值恰好也是 target,那么这个节点也应该被删除。也就是说,你需要重复此过程直到不能继续删除。
示例 1:Leetcode刷题——树篇6_第4张图片
输入:root = [1,2,3,2,null,2,4], target = 2
输出:[1,null,3,null,4]
解释:
上面左边的图中,绿色节点为叶子节点,且它们的值与 target 相同(同为 2 ),它们会被删除,得到中间的图。
有一个新的节点变成了叶子节点且它的值与 target 相同,所以将再次进行删除,从而得到最右边的图。
示例 2:
Leetcode刷题——树篇6_第5张图片

输入:root = [1,3,3,3,2], target = 3
输出:[1,3,null,null,2]
示例 3:

Leetcode刷题——树篇6_第6张图片
输入:root = [1,2,null,2,null,2], target = 2
输出:[1]
解释:每一步都删除一个绿色的叶子节点(值为
2)。 示例 4:

输入:root = [1,1,1], target = 1 输出:[] 示例 5:

输入:root = [1,2,3], target = 1 输出:[1,2,3]

提示:

1 <= target <= 1000 每一棵树最多有 3000 个节点。 每一个节点值的范围是 [1, 1000] 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/delete-leaves-with-a-given-value
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析:本题关键在于一旦删除值为 target 的叶子节点,它的父节点就可能变成叶子节点,所以大致思路是:
1、先把左子树当成一棵树,进行删除叶子结点的操作,最后返回删除后的树,有可能左子树都删完了,返回空;右子树同理。
2、经过步骤1,也更新了左右孩子,这时候再判断是否为空和根节点的值是否为target,如果是就删除,返回NULL,如果不是就返回根节点。
3、左子树和右子树的操作都是递归进行。

题解代码(C++):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* removeLeafNodes(TreeNode* root, int target) {
        if(root==NULL) return NULL;
        root->left = removeLeafNodes(root->left,target);
        root->right = removeLeafNodes(root->right,target);
        if(root->left==NULL && root->right==NULL && root->val==target)
            return NULL;
        else
            return root;
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode removeLeafNodes(TreeNode root, int target) {
        if(root==null) return null;
        root.left = removeLeafNodes(root.left,target);
        root.right= removeLeafNodes(root.right,target);
        if(root.left==null && root.right==null && root.val ==target)
            return null;
        else
            return root;
    }
}

题解代码(Python):

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def removeLeafNodes(self, root: TreeNode, target: int) -> TreeNode:
        if root is None:
            return None
        root.left=self.removeLeafNodes(root.left,target)
        root.right=self.removeLeafNodes(root.right,target)
        if root.left is None and root.right is None and root.val == target:
            return None
        else:
            return root

6.5、513. 找树左下角的值

给定一个二叉树,在树的最后一行找到最左边的值。

示例 1:

输入:

   2   
  / \   
 1   3

输出: 1

示例 2:

输入:

    1
   / \
  2   3
 /   / \
4   5   6
   /
  7

输出: 7

注意: 您可以假设树(即给定的根节点)不为 NULL。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-bottom-left-tree-value
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析:层次遍历,每层输出到一个vector,取最后一个vector的第一个元素即可。

题解代码(C++):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        vector<vector<int>> res;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty()){
            int count = q.size();
            vector<int> v;
            while(count>0){
                TreeNode* cur = q.front();q.pop();
                v.push_back(cur->val);
                if(cur->left!=NULL) q.push(cur->left);
                if(cur->right!=NULL) q.push(cur->right);
                count--;
            }
            res.push_back(v);
        }
        return res[res.size()-1][0];
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int findBottomLeftValue(TreeNode root) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        Queue<TreeNode> q = new LinkedList<TreeNode>();
        q.offer(root);
        while(!q.isEmpty()){
            int count = q.size();
            List<Integer> v = new ArrayList<>();
            while(count>0){
                TreeNode cur = q.poll();
                v.add(cur.val);
                if(cur.left!=null) q.offer(cur.left);
                if(cur.right!=null) q.offer(cur.right);
                count--;
            }
            res.add(v);
        }
        return res.get(res.size()-1).get(0);
    }
}

题解代码(Python):

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def findBottomLeftValue(self, root: TreeNode) -> int:
        res = []
        q = []
        q.append(root)
        while len(q)>0:
            count = len(q)
            v = []
            while count>0:
                cur = q.pop(0)
                v.append(cur.val)
                if cur.left is not None:
                    q.append(cur.left)
                if cur.right is not None:
                    q.append(cur.right)
                count-=1
            res.append(v)
        return res[-1][0]

6.6、114. 二叉树展开为链表

给定一个二叉树,原地将它展开为链表。

例如,给定二叉树

    1    
   / \   
  2   5 
 / \   \ 
 3   4   6 

将其展开为:
Leetcode刷题——树篇6_第7张图片

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析:很简单的思路,先把左子树展平,然后把右子树展平,最后连接起来即可。
主要分为两种情况:如果没有左子树,直接展平右子树即可
如果有左子树,先展平左子树,然后左子树最后一个结点连接到展平后的右子树,然后修改根节点的连接。

题解代码(C++):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* flattenHelper(TreeNode* root){
        if(root==NULL) return NULL;
        if(root->left!=NULL){
            flattenHelper(root->left);
            TreeNode* join = root->left;
            while(join->right!=NULL) join = join->right;
            join->right = flattenHelper(root->right);
            root->right = root->left;
            root->left=NULL;
        }else{
            root->right=flattenHelper(root->right);
        }
        return root;  
    }
    void flatten(TreeNode* root) {
        if(root==NULL) return;
        flattenHelper(root);
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode flattenHelper(TreeNode root){
        if(root==null) return null;
        if(root.left==null){
            root.right = flattenHelper(root.right);
        }else{
            flattenHelper(root.left);
            TreeNode join = root.left;
            while(join.right!=null) join = join.right;
            join.right = flattenHelper(root.right);
            root.right = root.left;
            root.left = null; 
        }
        return root;
    }
    public void flatten(TreeNode root) {
        if(root==null) return;
        flattenHelper(root);
    }
}

题解代码(Python):

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def flatten(self, root: TreeNode) -> None:
        """
        Do not return anything, modify root in-place instead.
        """
        self.flattenHelper(root)
    
    def flattenHelper(self,root:TreeNode)->TreeNode:
        if root is None:
            return None
        if root.left is None:
            root.right = self.flattenHelper(root.right)
        else:
            self.flattenHelper(root.left)
            join = root.left
            while join.right is not None:
                join = join.right
            join.right = self.flattenHelper(root.right)
            root.right = root.left
            root.left = None
        return root

6.7、222. 完全二叉树的节点个数

给出一个完全二叉树,求出该树的节点个数。

说明:

完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

示例:

输入:

    1    
   /  \   
  2    3  
 / \  / 
4  5 6

输出: 6

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-complete-tree-nodes
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析:最简单的思路就是利用遍历,为线性时间。
但是最佳的是利用完全二叉树的特性,效率较高。
假设完全二叉树的深度为d,那么除去最底层的结点,就有2d-1-1个结点,然后统计一下最底层的节点数即可。
现在问题是如何统计最底层的节点数?
可以使用二分查找!!!
把最底层的结点看成是一个数组:
Leetcode刷题——树篇6_第8张图片
虚线代表的是不存在的结点,首先第一轮是检查middle的结点存在不存在;
Leetcode刷题——树篇6_第9张图片
然后第二轮再检查middle位置的结点是否存在,最终定位到letf==right的结点
Leetcode刷题——树篇6_第10张图片
由此就能统计到最底层结点的数量了。

题解代码(C++):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int res = 0;
    void dfs(TreeNode* root){
        if(root==NULL) return;
        this->res++;
        dfs(root->left);
        dfs(root->right);
    }
    int countNodes(TreeNode* root) {
        this->res = 0;
        dfs(root);
        return this->res;
    }
};
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool exists(TreeNode* root,int index,int depth){
        int left = 0,right=(1<<depth)-1;
        int mid = 0;
        TreeNode* cur = root;
        while(depth>0){
            mid = (left+right)/2;
            if(index<=mid) {cur = cur->left;right=mid;}
            else {cur = cur->right;left=mid+1;}
            depth--;
        }
        return cur!=NULL;
    }
    int countNodes(TreeNode* root) {
        if(root==NULL) return 0;
        int depth = 0;
        TreeNode* cur=root;
        while(cur!=NULL){
            depth++;
            cur = cur->right;
        }
        int top = (1<<depth)-1;//最底层以上的结点数量
        //下面计算最底层的结点数量
        int left=0,right=(1<<depth)-1,mid=0;
        while(left<right){
            mid = (left+right)/2;
            if(exists(root,mid,depth)) left=mid+1;
            else right = mid-1;
        }
        if(exists(root,left,depth)) return top+left+1;
        else return top+left;
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    boolean exists(TreeNode root,int index,int depth){
        int left = 0,right=(1<<depth)-1;
        int mid =0;
        TreeNode cur = root;
        while(depth>0){
            mid = (left+right)/2;
            if(index<=mid) {cur = cur.left;right=mid;}
            else{cur = cur.right;left=mid+1;}
            depth--;
        }
        return cur!=null;
    }
    public int countNodes(TreeNode root) {
        if(root==null) return 0;
        int depth = 0;
        TreeNode cur =root;
        while(cur!=null){
            depth++;
            cur=cur.right;
        }
        int top = (1<<depth)-1;
        int left=0,right=(1<<depth)-1,mid=0;
        while(left<right){
            mid = (left+right)/2;
            if(exists(root,mid,depth)) left=mid+1;
            else right = mid-1;
        }
        if(exists(root,left,depth)) return top+left+1;
        else return top+left;

    }
}

题解代码(Python):

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def exists(self,root:TreeNode,index:int,depth:int)->bool:
        left,right=0,2**depth-1
        cur = root
        while depth>0:
            mid = (left+right)//2
            if index<= mid:
                cur = cur.left
                right = mid
            else:
                cur = cur.right
                left = mid+1
            depth-=1
        return cur is not None

    def countNodes(self, root: TreeNode) -> int:
        if root is None:
            return 0
        depth = 0
        cur = root
        while cur is not None:
            depth+=1
            cur = cur.right
        top = 2**depth-1

        left,right = 0,2**depth-1
        while left<right:
            mid = (left+right)//2
            if self.exists(root,mid,depth):
                left = mid+1
            else:
                right = mid-1
        
        if self.exists(root,left,depth):
            return top+left+1
        else:
            return top+left

6.8、106. 从中序与后序遍历序列构造二叉树

根据一棵树的中序遍历与后序遍历构造二叉树。

注意: 你可以假设树中没有重复的元素。

例如,给出

中序遍历 inorder = [9,3,15,20,7] 后序遍历 postorder = [9,15,7,20,3] 返回如下的二叉树:

 3    
/ \   
9  20
  /  \    
 15   7

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析:可以由中序遍历和后序遍历唯一确定一棵二叉树,根据后序遍历可以确定根节点,而中序遍历可以确定分组。

题解代码(C++):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> postorder;
    int index;
    map<int,int> mymap;
    TreeNode* buildTreeHelper(int left,int right){
        if(left>right) return NULL;
        int val = this->postorder[this->index--];
        TreeNode* root = new TreeNode(val);
        root->right = buildTreeHelper(this->mymap[val]+1,right);
        root->left = buildTreeHelper(left,this->mymap[val]-1);
        return root;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        this->mymap.clear();
        for(int i=0;i<inorder.size();i++){
            this->mymap[inorder[i]] = i;
        }
        this->index = inorder.size()-1;
        this->postorder = postorder;
        return buildTreeHelper(0,inorder.size()-1);
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int index;
    int[] postorder;
    Map<Integer,Integer> mymap = new HashMap<>();
    public TreeNode buildTreeHelper(int left,int right){
        if(left>right) return null;
        int val = this.postorder[this.index--];
        TreeNode root = new TreeNode(val);
        root.right = buildTreeHelper(this.mymap.get(val)+1,right);
        root.left = buildTreeHelper(left,this.mymap.get(val)-1);
        return root;
    }
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        this.index = postorder.length-1;
        this.postorder = postorder;
        for(int i=0;i<inorder.length;i++){
            this.mymap.put(inorder[i],i);
        }
        return buildTreeHelper(0,inorder.length-1);
    }
}

题解代码(Python):

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode:
        def helper(left:int,right:int)->TreeNode:
            if left>right:
                return None
            val = postorder.pop()
            root = TreeNode(val)
            root.right = helper(mymap[val]+1,right)
            root.left = helper(left,mymap[val]-1)
            return root
        mymap = {val:idx for idx,val in enumerate(inorder)}
        return helper(0,len(inorder)-1)

6.9、1104. 二叉树寻路

在一棵无限的二叉树上,每个节点都有两个子节点,树中的节点 逐行 依次按 “之” 字形进行标记。

如下图所示,在奇数行(即,第一行、第三行、第五行……)中,按从左到右的顺序进行标记;

而偶数行(即,第二行、第四行、第六行……)中,按从右到左的顺序进行标记。
Leetcode刷题——树篇6_第11张图片
给你树上某一个节点的标号 label,请你返回从根节点到该标号为 label 节点的路径,该路径是由途经的节点标号所组成的。
示例 1:
输入:label = 14 输出:[1,3,4,14]
示例 2:
输入:label = 26 输出:[1,2,6,10,26]
提示:

1 <= label <= 106

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/path-in-zigzag-labelled-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析:找规律的题目。
Leetcode刷题——树篇6_第12张图片
假如结点的值都转化为二进制,就得到上图的树,怎么找规律呢?
例如label=14,输出结果为[1,3,4,14]
那么14=1110b 如何转为4=0100b呢?
首先右移一位得到0111b=7,然后最后两位取反得到0100b=4
0100b=4右移一位得到0010b,然后最后一位取反得到0011b=3
0011b=3右移一位得到0001b,然后最后0位取反得到0001b=1
就是这么一个规律。

怎么知道是按最后多少位取反呢?首先是确定label所在层数d,d=上取整log2(label),例如label=14,d=4,2=d-2;
如何按最后两位取反?使用异或运算,0异或a = a,1异或a = a的取反。

题解代码(C++):

class Solution {
public:
    vector<int> pathInZigZagTree(int label) {
        vector<int> res;
        int d = log(label)/log(2);
        if(d==0) {res.push_back(1);return res;}
        int mask = (1<<(d-1))-1;
        while(label>1){
            res.push_back(label);
            label = label>>1;
            label = label ^ mask;
            mask = mask>>1;
        }
        res.push_back(1);
        reverse(res.begin(),res.end());
        return res;
    }
};

题解代码(Java):

class Solution {
    public List<Integer> pathInZigZagTree(int label) {
        List<Integer> res = new LinkedList<Integer>();
        int d = (int)(Math.log(label)/Math.log(2));
        if(d==0){res.add(1);return res;}
        int mask = (1<<(d-1))-1;
        while(label>1){
            res.add(label);
            label = label>>1;
            label = label^mask;
            mask = mask>>1;
        }
        res.add(1);
        Collections.reverse(res);
        return res;
    }
}

题解代码(Python):

class Solution:
    def pathInZigZagTree(self, label: int) -> List[int]:
        res = []
        d = int(log(label)/log(2))
        if d ==0:
            res.append(1)
            return res
        mask = (1<<(d-1))-1
        while label>1:
            res.append(label)
            label = label>>1
            label = label ^ mask
            mask = mask >>1
        res.append(1)
        res.reverse()
        return res

6.10、979. 在二叉树中分配硬币

给定一个有 N 个结点的二叉树的根结点 root,树中的每个结点上都对应有 node.val 枚硬币,并且总共有 N 枚硬币。

在一次移动中,我们可以选择两个相邻的结点,然后将一枚硬币从其中一个结点移动到另一个结点。(移动可以是从父结点到子结点,或者从子结点移动到父结点。)。

返回使每个结点上只有一枚硬币所需的移动次数。

示例 1:

Leetcode刷题——树篇6_第13张图片

输入:[3,0,0] 输出:2
解释:从树的根结点开始,我们将一枚硬币移到它的左子结点上,一枚硬币移到它的右子结点上。
示例 2:
Leetcode刷题——树篇6_第14张图片
输入:[0,3,0] 输出:3 解释:从根结点的左子结点开始,我们将两枚硬币移到根结点上
[移动两次]。然后,我们把一枚硬币从根结点移到右子结点上。 示例 3:
Leetcode刷题——树篇6_第15张图片
输入:[1,0,2] 输出:2
示例 4:
Leetcode刷题——树篇6_第16张图片
输入:[1,0,0,null,3] 输出:4
提示:
1<= N <= 100
0 <= node.val <= N
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/distribute-coins-in-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析:
Leetcode刷题——树篇6_第17张图片
这个问题是移动金币的问题,首先有左右孩子的结点有两个移动方向,若其还有父节点,那么就有三个移动方向,这是很不便于分析的。
如果是只有一个孩子的结点就有一个移动方向,若其还有父节点,那么也有两个移动方向,也是不便于分析。
没有孩子的结点,也就是叶子节点,移动方向就只有一个了,看叶子结点的值就能知道移进或移出金币的步数:abs(val-1)
Leetcode刷题——树篇6_第18张图片
总绝对值为4,表示需要4步才能完成对叶子结点的金币移动。
此时,叶子结点就不再考虑了,而是要考虑倒数第二层的结点。
Leetcode刷题——树篇6_第19张图片
为什么第二层的左边的0结点变成1了呢?可以理解成它从左右孩子结点分别是移入2个,移出1个,剩下1个。
Leetcode刷题——树篇6_第20张图片
就是上图这种样子,而且步数也计算了abs(2)+abs(-1) =3,需要3步能完成。
类似这样,从叶子结点一层层解决,使用后序遍历的方式就可以完成。

题解代码(C++):

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int dfs(TreeNode* root,int &res){
        if(root==NULL) return 0;
        int left = dfs(root->left,res);//计算左子树完成多余(所需)的金币数
        int right = dfs(root->right,res);//计算右子树完成多余(所需)的金币数
        res= res + abs(left) + abs(right);//移动步数累加
        return root->val+left+right-1;//当前结点多余(所需)的金币数
    }
    int distributeCoins(TreeNode* root) {
        int res =0;
        dfs(root,res);
        return res;
    }
};

题解代码(Java):

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int res =0;
    public int dfs(TreeNode root){
        if(root==null) return 0;
        int left = dfs(root.left);
        int right = dfs(root.right);
        this.res = this.res + Math.abs(left) + Math.abs(right);
        return root.val+left+right-1;
    }
    public int distributeCoins(TreeNode root) {
        this.res = 0;
        dfs(root);
        return this.res;
    }
}

题解代码(Python):

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def __init__(self):
        self.res = 0

    def dfs(self,root:TreeNode)->int:
        if root is None:
            return 0
        left = self.dfs(root.left)
        right = self.dfs(root.right)
        self.res = self.res + abs(left)+abs(right)
        return root.val+left+right-1
            
    def distributeCoins(self, root: TreeNode) -> int:
        self.res = 0
        self.dfs(root)
        return self.res

你可能感兴趣的:(刷题打基础系列)