自学内容网 自学内容网

[代码随想录Day16打卡] 找树左下角的值 路径总和 从中序与后序遍历序列构造二叉树

找树左下角的值

定义:二叉树中最后一行最靠左侧的值。
前序,中序,后序遍历都是先遍历左然后遍历右。
因为优先遍历左节点,所以递归中因为深度增加更新result的时候,更新的值是当前深度最左侧的值,到最后就得到了最后一行最靠左的节点。
注意:其中也有回溯,depth++; traversal(root->left,depth); depth–;这里,为什么用函数处理完之后depth要–?因为在处理完左节点的深度后,要减掉左节点的深度,然后再处理右节点的深度。
下面是C++, JAVA, Python的代码。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int maxDepth = INT_MIN;//int中的最小值
    int result;//记录节点的值
    void traversal(TreeNode* root, int depth){
        if(root->left == NULL && root->right == NULL){
            if(depth > maxDepth){
                maxDepth = depth;
                result = root->val;//如果深度增加就更新result保存的节点的值,因为遍历顺序是坐在右的前面所以能让result更新的一定是当前深度下的最左边的节点
            }
        }
        //然后处理左节点的值
        if(root->left){
            depth++;
            traversal(root->left, depth);
            depth--;//回溯
        }//这三行就相当于traversal(root->left, depth+1)//做了++操作但是没有改变depth的值
        if(root->right){
            depth++;
            traversal(root->right, depth);
            depth--;
        }
    }
    int findBottomLeftValue(TreeNode* root) {
       int depth = 0;
       traversal(root, depth);
       return result;
    }
};
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    private int maxDepth = -1;
    private int result;
    void traversal(TreeNode root, int depth){
        if(root.left == null && root.right==null){//碰到叶子节点了来比较当前叶子节点的深度和最大深度
            if(depth > maxDepth){
                maxDepth = depth;
                result = root.val;
            }
        }
        //处理左节点
        if(root.left!=null){
            depth++;
            traversal(root.left, depth);
            depth--;//这三行相当于traversal(root.left, depth+1)
        }
        //处理右节点
        if(root.right!=null){
            depth++;
            traversal(root.right, depth);
            depth--;//这三行相当于traversal(root.right, depth+1)
        }

    }
    public int findBottomLeftValue(TreeNode root) {
        int depth = 0;
        traversal(root, depth);
        return result;
    }
}
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    
    def traversal(self, root, depth):
        
        if root.left==None and root.right==None:
            if depth > self.maxDepth:#如果当前深度比最大深度大,更新result的值
                self.maxDepth = depth
                self.result = root.val
        if root.left!=None:
            depth+=1
            self.traversal(root.left, depth)
            depth-=1
        if root.right!=None:
            depth+=1
            self.traversal(root.right, depth)
            depth-=1
        
    def findBottomLeftValue(self, root):
        """
        :type root: Optional[TreeNode]
        :rtype: int
        """
        self.maxDepth = -1
        self.result = None
        depth = 0
        self.traversal(root, depth)
        return self.result
        

参考文章

  1. https://programmercarl.com/0513.%E6%89%BE%E6%A0%91%E5%B7%A6%E4%B8%8B%E8%A7%92%E7%9A%84%E5%80%BC.html

路径总和

在这里插入图片描述

我们在递归外面用目标值减去根节点的值得到新的目标值,这样之后不必处理中也就是节点本身,而是处理节点的左右子节点。前中后序都一样(因为没有对中进行操作,只对左右进行操作)。

  1. 确定递归函数的参数和返回值:参数node和 count,输出是bool类型。如果它遍历的一条子路径符合要求就一层一层向上返回true。
  2. 确定终止条件:因为对左右子节点进行操作,所以要避免左右子节点为空,如果为空,count为0符合要求返回True,如果左右节点为空,count不为0不符合要求,返回False。
  3. 确定单层递归的逻辑:count减去当前的left/right节点,然后放到递归函数中判断。回溯的时候count+上当前的left/right节点。
    下面是C++,JAVA和Python代码。
    其中也用到了回溯,再理解一遍回溯思想。在处理左右节点的时候的函数。
count-=node->left->val;
if(traversal(node->left, count)) return true;
count += node->left->val;

我看弹幕上有人说:发现这条路径最后count不是0不符合条件的情况下,需要找到别的路径,这就需要退回去找。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        if(root){
            int count = targetSum-root->val;
            return traversal(root, count);
        }
        return false;
    }
    bool traversal(TreeNode* node, int count){
        if(node->left==NULL && node->right==NULL && count==0) return true;
        if(node->left==NULL && node->right==NULL && count!=0) return false;
        if(node->left){//要判断左孩子不为空否则递归左孩子的时候会出现空指针异常
            count-=node->left->val;
            if(traversal(node->left, count)) return true;
            count += node->left->val;
        }
        if(node->right){
            count-=node->right->val;
            if(traversal(node->right, count)) return true;
            count += node->right->val;
        }
        return false;
    }
};
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    boolean traversal(TreeNode node, int count){
        if(node.left==null && node.right==null && count==0) return true;
        if(node.left==null && node.right==null && count!=0) return false;
        if(node.left!=null){
            count-=node.left.val;
            if(traversal(node.left, count)) return true;//函数中最开始进行判断
            count+=node.left.val;//回溯
        }
        if(node.right!=null){
            count-=node.right.val;
            if(traversal(node.right, count)) return true;
            count+=node.right.val;
        }
        return false;
    }
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root!=null){
            int count = targetSum-root.val;
            return traversal(root, count);
        }
        return false;
    }
}
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def hasPathSum(self, root, targetSum):
        """
        :type root: Optional[TreeNode]
        :type targetSum: int
        :rtype: bool
        """
        if(root!=None):
            count=targetSum-root.val
            return self.traversal(root, count)
        return False
    def traversal(self, node, count):
        if node.left==None and node.right==None and count==0:
            return True
        if node.left==None and node.right==None and count!=0:
            return False#说明这条路径不是
        if(node.left != None):
            count -= node.left.val
            if(self.traversal(node.left, count)):
                return True
            count += node.left.val
        if(node.right != None):
            count -= node.right.val
            if(self.traversal(node.right, count)):
                return True
            count += node.right.val
        return False

路径之和Ⅱ

在这里插入图片描述

给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
与上一个相比要定义vector<vector> result;存储所有的路径,vector path;存储当前路径。
下面是C++,JAVA和Python代码。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
private:
    vector<vector<int>> result;
    vector<int> path;
    //递归函数不需要返回值,因为我们要遍历整个树
    void traversal(TreeNode* cur, int count){
        if(!cur->left && !cur->right && count == 0){//遇到了叶子节点,而且找到了和为targetSum的路径
            result.push_back(path);
            return;
        }
        if(!cur->left && !cur->right) return; //如果遇到叶子节点,没有合适的路径就直接返回

        if(cur->left){//左,防止遍历空节点
            path.push_back(cur->left->val);//从后面加入
            count -= cur->left->val;
            traversal(cur->left, count);//递归
            count += cur->left->val;//下面两个都是回溯,就是递归到这个节点和出这个节点的两种情况下环境不变
            path.pop_back();//从后面弹出
        }
        if(cur->right){//左,防止遍历空节点
            path.push_back(cur->right->val);//从后面加入
            count -= cur->right->val;
            traversal(cur->right, count);//递归
            count += cur->right->val;//下面两个都是回溯,就是递归到这个节点和出这个节点的两种情况下环境不变
            path.pop_back();//从后面弹出
        }
        return;
    }
public:
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        result.clear();
        path.clear();
        if(root==NULL) return result;
        path.push_back(root->val);//把根节点放到路径
        traversal(root, targetSum - root->val);
        return result;
    }
};
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {

    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        List<List<Integer>> result = new ArrayList<>();
        if (root == null) return result; // 非空判断
        Deque<Integer> path = new LinkedList<>(); // 使用Deque
        path.add(root.val);
        traversal(root, targetSum - root.val, result, path);
        return result;
    }

    public void traversal(TreeNode root, int count, List<List<Integer>> result, Deque<Integer> path) {
        if (root.left == null && root.right == null && count == 0) {
            result.add(new ArrayList<>(path));
            return;
        }
        if (root.left == null && root.right == null) return; // 这条路径不符合要求

        if (root.left != null) { // 左子树
            path.addLast(root.left.val);
            count -= root.left.val;
            traversal(root.left, count, result, path);
            count += root.left.val;
            path.pollLast();
        }
        if (root.right != null) { // 右子树
            path.addLast(root.right.val);
            count -= root.right.val;
            traversal(root.right, count, result, path);
            count += root.right.val;
            path.pollLast();
        }
    }
}
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def __init__(self):
        self.result = []
        self.path = []
    def traversal(self, cur, count):
        if not cur.left and not cur.right and count == 0:#遇到了叶子节点而且找到了和为目标值的路径
            self.result.append(self.path[:])
            return 
        if not cur.left and not cur.right:#遇到了叶子节点但是路径不符合条件
            return
        if cur.left:#左 空节点不遍历
            self.path.append(cur.left.val)
            count-=cur.left.val
            self.traversal(cur.left, count)
            count += cur.left.val
            self.path.pop() #回溯
        if cur.right: #右 空节点不遍历
            self.path.append(cur.right.val)
            count -= cur.right.val
            self.traversal(cur.right, count) #递归
            count += cur.right.val #回溯
            self.path.pop() #回溯
        return
    def pathSum(self, root, targetSum):
        """
        :type root: Optional[TreeNode]
        :type targetSum: int
        :rtype: List[List[int]]
        """
        if not root:
            return self.result
        self.path.append(root.val)
        self.traversal(root, targetSum - root.val)
        return self.result

参考文章

  1. https://programmercarl.com/0112.%E8%B7%AF%E5%BE%84%E6%80%BB%E5%92%8C.html

从中序与后序遍历序列构造二叉树

下面是C++代码。
主要的步骤有6个:

  1. 后序数组为0,说明是空节点。
  2. 后续数组最后一个元素为节点元素。
  3. 寻找中序数组位置找切割点。
  4. 切割中序数组。
  5. 切割后序数组。
  6. 递归处理左区间和右区间。
    在这里插入图片描述
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
private:
    TreeNode* traversal (vector<int>& inorder, int inorderBegin, int inorderEnd, vector<int>& postorder, int postorderBegin, int postorderEnd){
        if (postorderBegin == postorderEnd) return NULL;

        int rootValue = postorder[postorderEnd - 1];
        TreeNode* root = new TreeNode(rootValue);

        if(postorderEnd - postorderBegin == 1) return root;
        int delimiterIndex;
        for(delimiterIndex = inorderBegin; delimiterIndex < inorderEnd; delimiterIndex++){
            if(inorder[delimiterIndex] == root->val) break;
        }
        //切割中序数组
        //左中序区间左闭右开
        int leftInorderBegin = inorderBegin;
        int leftInorderEnd = delimiterIndex;
        //右中序区间,左闭右开[rightInorderBegin, rightInorderEnd]
        int rightInorderBegin = delimiterIndex+1;
        int rightInorderEnd = inorderEnd;

        //切割后续数组
        // 左后序区间,左闭右开[leftPostorderBegin, leftPostorderEnd)
        int leftPostorderBegin =  postorderBegin;
        int leftPostorderEnd = postorderBegin + delimiterIndex - inorderBegin; // 终止位置是 需要加上 中序区间的大小size
        // 右后序区间,左闭右开[rightPostorderBegin, rightPostorderEnd)
        int rightPostorderBegin = postorderBegin + (delimiterIndex - inorderBegin);
        int rightPostorderEnd = postorderEnd - 1; // 排除最后一个元素,已经作为节点了
        root->left = traversal(inorder, leftInorderBegin, leftInorderEnd,  postorder, leftPostorderBegin, leftPostorderEnd);
        root->right = traversal(inorder, rightInorderBegin, rightInorderEnd, postorder, rightPostorderBegin, rightPostorderEnd);

        return root;
    }
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
       if(inorder.size()==0 || postorder.size()==0) return NULL;
       //左闭右开的原则
       return traversal(inorder, 0, inorder.size(), postorder, 0, postorder.size()); 
    }
};

参考文章

  1. https://programmercarl.com/0112.%E8%B7%AF%E5%BE%84%E6%80%BB%E5%92%8C.html

原文地址:https://blog.csdn.net/goodenough5/article/details/143868450

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!