leetcode刷题-二叉树04

代码随想录二叉树part04|110.平衡二叉树、257. 二叉树的所有路径、404.左叶子之和、513.找树左下角的值、112.路径总和、106.从中序与后序遍历序列构造二叉树

一刷直接过,二刷有精力的时候 再去掌握迭代法。

110.平衡二叉树

代码随想录文档讲解
LeetCode

判断 左子树和右子树是否小于等于1

如何判断呢?
判断每个节点的左右子树的高度差是否超过1
高度 vs 深度:
高度:距离叶子节点的距离
深度:距离根节点的距离

  	                                高度     深度
  	3                                  3         1
   /   \	
  9		20						    2   		2
  		/	\
  	  15	 7							1			3
                                 后序遍历  前序遍历

(后序通过左右孩子返回给父节点,层层向上返回,所以可以求高度;
前序 中左右 向下遍历,不向上返回结果)

伪代码c++

int getHeight( node  ){
	if (node == NULL) return 0; // 空节点的高度是0
	leftHeight = getHeight(node->left); // 左
	if(leftHeight==-1) return -1; // 左子树不是平衡二叉树
	rightHeight = getHeight(node->right); // 右
	if(rightHeight==-1) return -1; // 右子树不是平衡二叉树
	int result;
	if(abs(rightHeight - leftHeight) > 1)  return -1;
	else return 1 + max(leftHeight, rightHeight); 
}

需要额外写一个辅助函数(用于计算高度的函数)

python代码

class Solution:
    def isBalanced(self, root: Optional[TreeNode]) -> bool:
        if self.getHeight(root) == -1:
            return False
        else:
            return True
        
    def getHeight(self, root):
        if not root:
            return 0
        leftHeight = self.getHeight(root.left)
        if leftHeight == -1:
            return -1
        rightHeight = self.getHeight(root.right)
        if rightHeight == -1:
            return -1
        if abs(rightHeight - leftHeight) > 1:
            return -1
        else:
            return 1 + max(rightHeight, leftHeight)

257. 二叉树的所有路径 回溯法 需要再回顾

leetcode题目链接
代码随想录文档讲解

思路

递归法使用前序遍历,
回溯法,

伪代码(C++)

void travesal (TreeNode node, void<int> &path, vector<string> &result){
	// 中 要写在前面,否则会落下叶子节点
	path.push_back(node->val) 
	if(node->left==NULL && node->right==NULL){ //遍历到叶子节点回溯
		result.push_back(path); // path需要进行进一步处理,这里简化
		return;
	}
	// 左
	if(node->left){
		travesal(node->left, path, result); // 递归
		path.pop_back(); //回溯
	}
	// 右
	if(node->right){
		travesal(node->right, path, result);
		path.pop_back();
	}		
}

python代码

class Solution:
    def traversal(self, cur, path, result):
        path.append(cur.val)
        if not cur.left and not cur.right:
            spath = '->'.join(map(str, path))
            result.append(spath)
        if cur.left:
            self.traversal(cur.left, path, result)
            path.pop()
        if cur.right:
            self.traversal(cur.right, path, result)
            path.pop()
    def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
        result = list()
        path = list()
        if not root:
            return result
        self.traversal(root, path, result)
        return result

404.左叶子之和 写完了 但还不太懂

leetcode题目链接
代码随想录文档讲解

思路

左叶子节点:叶子节点中 && 父节点的左孩子
要通过父节点判断子节点是不是我们要收集的元素,一层一层收集左叶子之和,向上返回
用后序遍历代码相对简洁 + 回溯

伪代码(C++)

int traversal( TreeNode node ) {
	if(node==NULL) return 0;  // 空节点
	if(node->left==NULL && node->right==NULL) return 0; // 叶子节点
	// 左
	int leftNum = traversal(node->left);
	if(node->left != NULL && node->left->left==NULL && node->left->right==NULL){
		leftNum = node->left->val;
	}
	// 右
	int rightNum = traversal(node->right);
	// 中
	int sum = leftNum + rightNum;
	return sum;
}

python代码

class Solution:
    def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
        if not root: return 0
        if not root.left and not root.right: return 0
        leftnum = self.sumOfLeftLeaves(root.left)
        if root.left and not root.left.left and not root.left.right:
            leftnum = root.left.val
        rightnum = self.sumOfLeftLeaves(root.right)
        Sum = leftnum + rightnum
        return Sum

513.找树左下角的值

leetcode题目链接
代码随想录文档讲解

思路

迭代法
递归法

深度最大的叶子节点,使用前中后序遍历都可(只要先遍历左节点)

伪代码(C++)

int maxDepth = INT_MIN; // 记录最大深度
int result;  // 叶子结点的值
void trversal(root, depth){
	if(root->left==NULL && root->right==NULL)
		if(depth>maxDepth) {
			maxDepth = depth;
			result = root->val;
		}
	}
	// 左:只要左在右的前面即可
	if(root->left){
		depth++;
		traversal(node->left, depth);
		depth--; // 回溯
	}  / 这3行可以缩写为: traversal(node->left, depth+1)
	// 右
	if(root->right){
		depth++;
		traversal(node->right, depth);
		depth--;
	}
}

python代码

class Solution:
    def traversal(self, root, depth):
        if not root.left and not root.right:
            if depth > self.maxDepth:
                self.maxDepth = depth
                self.result = root.val
        if root.left:
            depth += 1
            self.traversal(root.left, depth)
            depth -= 1
        if root.right:
            depth += 1
            self.traversal(root.right, depth)
            depth -= 1
        return self.result
        
    def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
        self.maxDepth = 0
        self.result = root.val
        return self.traversal(root, 1)

112. 路径总和

leetcode题目链接
代码随想录文档讲解

思路

注意: 必须要到叶子节点的总和,return的写法,递归完后也要return
if traversal(node->left, count) return true;

没有中的处理逻辑,前中后序遍历都可以
没有必要全都遍历完,找到一条路径立刻返回即可

伪代码(C++)

bool traversal(TreeNode node, int count); // 传入目标值,做减法
	if(node->left==NULL && node->right==NULL && count==0) // 到叶子节点,减为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;
}		

python代码

# 我的代码
class Solution:
    def traversal(self, node, thesum):
        if not node.left and not node.right and thesum == self.targetSum:
            return True
        if node.left:
            thesum += node.left.val
            if self.traversal(node.left, thesum):
                return True
            thesum -= node.left.val
        if node.right:
            thesum += node.right.val
            if self.traversal(node.right, thesum):
                return True
            thesum -= node.right.val
        return False
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        if not root: return False
        self.targetSum = targetSum
        return self.traversal(root, root.val)

路径总和Ⅱ

代码注意要点:

  1. self.result.append(path[:]) 而不是 self.result.append(path)
    列表是可变数据结构,加:切片是深拷贝;不加的话是浅拷贝,之后就变了
  2. self.result 设置为类的私有属性
class Solution:
    def traversal(self, node, thesum, path):
        # print(path)
        # print(thesum)
        # print(self.result)
        print('-------------')
        if not node.left and not node.right and thesum==self.targetSum:
            self.result.append(path[:])
            return
        if not node.left and not node.right:
            return
        if node.left:
            path.append(node.left.val)
            thesum += node.left.val
            self.traversal(node.left, thesum, path)
            thesum -= node.left.val
            path.pop()
        if node.right:
            path.append(node.right.val)
            thesum += node.right.val
            self.traversal(node.right, thesum, path)
            thesum -= node.right.val
            path.pop()
        return

    def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
        self.result = []
        path = []
        self.targetSum = targetSum
        if not root: return self.result
        path.append(root.val)
        self.traversal(root, root.val, path)
        return self.result

路径总和Ⅲ

思路与前面的不一样了,注意!

使用递归法,深度优先遍历,不需要回溯!分别遍历以每一个节点为开始可能的路径。
注意递归的结束条件,如果这个节点的值即为我们要找的值,count+=1

class Solution:
    def pathSum(self, root: Optional[TreeNode], targetSum: int) -> int:
        def rootSum(root, targetSum):
            if not root:
                return 0
            ret = 0
            if root.val == targetSum:
                ret += 1
            ret += rootSum(root.left, targetSum - root.val)
            ret += rootSum(root.right, targetSum - root.val)
            return ret
        if root is None:
            return 0
        ret = rootSum(root, targetSum)
        ret += self.pathSum(root.left, targetSum)
        ret += self.pathSum(root.right, targetSum)
        return ret

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

leetcode题目链接
代码随想录文档讲解

思路

递归

伪代码(C++)



python代码

class Solution:
    def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode:
        # 第一步: 特殊情况讨论: 树为空. (递归终止条件)
        if not postorder:
            return None

        # 第二步: 后序遍历的最后一个就是当前的中间节点.
        root_val = postorder[-1]
        root = TreeNode(root_val)

        # 第三步: 找切割点.
        separator_idx = inorder.index(root_val)

        # 第四步: 切割inorder数组. 得到inorder数组的左,右半边.
        inorder_left = inorder[:separator_idx]
        inorder_right = inorder[separator_idx + 1:]

        # 第五步: 切割postorder数组. 得到postorder数组的左,右半边.
        # ⭐️ 重点1: 中序数组大小一定跟后序数组大小是相同的.
        postorder_left = postorder[:len(inorder_left)]
        postorder_right = postorder[len(inorder_left): len(postorder) - 1]

        # 第六步: 递归
        root.left = self.buildTree(inorder_left, postorder_left)
        root.right = self.buildTree(inorder_right, postorder_right)
         # 第七步: 返回答案
        return root
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值