文章目录
[Nowcoder]2020/11/28
二叉树根节点到叶子节点的所有路径和
解题思路
深度遍历
利用递归实现先序遍历,如果碰到叶子结点返回当前所走路径计算的值,如果不是则继续进行先序遍历。
Python
class Solution:
def sumNumbers(self , root ):
# 如果是空结点,返回0值
if root is None:
return 0
# 递归函数
def sub(root, sums):
# 计算到当前点的累加值即sums
if root is None:
return 0
# 如果此结点非空就累加至sums
sums = sums*10 + root.val
# 如果此点恰好为叶子结点就直接返回sums值
if root.left is None and root.right is None:
return sums
# 如果此点不是叶子结点,就同时向左右子树遍历
# 自底向下的传递回累加值
return sub(root.left, sums)+sub(root.right,sums)
return sub(root, 0)
Java
public int sub (TreeNode root, int sums){
if (root == null)
return 0;
sums = sums * 10 + root.val;
if (root.left == null && root.right == null)
return sums;
return sub(root.left, sums) + sub(root.right, sums);
}
public int sumNumbers (TreeNode root) {
// write code here
if (root == null)
return 0;
return sub(root, 0);
}
广度遍历
Python
class Solution:
def sumNumbers(self , root ):
if not root:
return 0
total = 0
nodeQueue = collections.deque([root])
numQueue = collections.deque([root.val])
while nodeQueue:
node = nodeQueue.popleft()
num = numQueue.popleft()
left, right = node.left, node.right
if not left and not right:
total += num
else:
if left:
nodeQueue.append(left)
numQueue.append(num*10 + left.val)
if right:
nodeQueue.append(right)
numQueue.append(num*10 + right.val)
return total
Java
class Solution {
public int sumNumbers(TreeNode root) {
if (root == null) {
return 0;
}
int sum = 0;
Queue<TreeNode> nodeQueue = new LinkedList<TreeNode>();
Queue<Integer> numQueue = new LinkedList<Integer>();
nodeQueue.offer(root);
numQueue.offer(root.val);
while (!nodeQueue.isEmpty()) {
TreeNode node = nodeQueue.poll();
int num = numQueue.poll();
TreeNode left = node.left, right = node.right;
if (left == null && right == null) {
sum += num;
} else {
if (left != null) {
nodeQueue.offer(left);
numQueue.offer(num * 10 + left.val);
}
if (right != null) {
nodeQueue.offer(right);
numQueue.offer(num * 10 + right.val);
}
}
}
return sum;
}
}
二叉树的最大路径和
递归函数在向下递归的同时,返回此路径下叶子节点到当前值的最大和值。
Python
class Solution:
def maxPathSum(self , root ):
ans = -math.inf
def sub(root):
nonlocal ans
if root is None:
return 0
maxl = max(0, sub(root.left))
maxr = max(0, sub(root.right))
# 注意此地的三个比较
ans = max(ans, max(root.val+max(mal, maxr), root.val + maxl + maxr))
return max(maxl, maxr)+root.val
sub(root)
return ans
找到搜索二叉树中两个错误的节点
这一道题在牛客网中相同的算法用python写会运行超时,以下用Java解答。
主要的两个点:
- 中序遍历二叉搜索树输出的是一个递增序列
- 当序列中出现两次降序时,取第一次的前一个数,第二次的后一个数;当只有一次降序时,就取这两个数。
public int[] findError (TreeNode root) {
int [] ans = new int[2];
ans[0]=ans[1]=0;
LinkedList<TreeNode> stack = new LinkedList<>();
TreeNode prev = null;
while (!stack.isEmpty() || root != null){
if (root != null){
stack.offer(root);
root = root.left;
}else{
root = stack.removeLast();
if (prev != null && prev.val > root.val){
if (ans[1] == 0)
ans[1] = prev.val;
ans[0] = root.val;
// 这里如果直接加return 就只考虑了一次降序的情况
}
prev = root;
root = root.right;
}
}
return ans;
}
圆盘取数
一个刻有字母的圆盘,用字符串plate表示(从圆盘正上方开始顺时针阅读),通过旋转该圆盘找到目标词target,并使得旋转次数最少。每次可以顺时针或逆时针转一格,给出最少旋转次数。
plate:“cabfa”, target:“caf”
result = 2
// 核心思想是递归
// 如果题目限定只传入plate target那就调用这个递归函数
public int find(int index, int index_targetChar, String plate, String target){
// 如果找完了就返回0
if (index_targetChar == target.length())
return 0;
// 分别记录左右两边走的步数
int left_step = 0, right_step = 0;
int plate_len = plate.length();
boolean isOver = false;
while(!isOver){
// 找出走步数后对应的坐标
int left_index = (index - left_step + plate_len)%plate_len;
int right_index = (index+right_step)%plate_len;
// 这里需要注意:
// 1.如果左边先找到,跳出循环时left_step和right_step是相等的
// 2.如果右边先找到,跳出循环时left_step - 1 = right_step
if (target.charAt(index_targetChar) == plate.charAt(left_index)){
isOver = true;
}else left_step++;
if (target.charAt(index_targetChar) == plate.charAt(right_index)){
isOver = true;
}else right_step++;
}
if (left_step > right_step){
// 如果左边步数大于右边步数则向右转进行递归
int step = find((index + right_step)%plate_len, index_targetChar+1, plate, target);
return right_step + step;
}else if (left_step < right_step){
// 如果左边步数小于右边步数则向右转进行递归
int step = find((index - left_step + plate_len)%plate_len, index_targetChar+1, plate, target);
return left_step + step;
}else{
// 如果左边步数等于右边步数则向左进行递归,因为上面的注意点1
int lans = find((index - left_step + plate_len)%plate_len, index_targetChar+1, plate, target);
if (left_step != 0){
int rans = find((index + right_step)%plate_len, index_targetChar+1, plate, target);
// 取左右中的最小值
return left_step + Math.min(rans, lans);
}
else return left_step + lans;// 如果指向的刚好就是要找的字母
}
}
/*
public static void main(String[] args){
String plate = "cabfa";
String target = "caf";
Test t = new Test();
int ans = t.find(0, 0, plate, target);
System.out.println(ans);
}
*/