[Nowcoder]2020/11/28

[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解答。

主要的两个点:

  1. 中序遍历二叉搜索树输出的是一个递增序列
  2. 当序列中出现两次降序时,取第一次的前一个数,第二次的后一个数;当只有一次降序时,就取这两个数。
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);
    }
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值