leetcode笔记——129求根到叶子结点的数字之和

题目:

给定一个二叉树,它的每个结点都存放一个 0-9 的数字,每条从根到叶子节点的路径都代表一个数字。

例如,从根到叶子节点路径 1->2->3 代表数字 123

计算从根到叶子节点生成的所有数字之和。

说明: 叶子节点是指没有子节点的节点。

示例 1:

输入: [1,2,3]
    1
   / \
  2   3
输出: 25
解释:
从根到叶子节点路径 1->2 代表数字 12.
从根到叶子节点路径 1->3 代表数字 13.
因此,数字总和 = 12 + 13 = 25.

示例 2:

输入: [4,9,0,5,1]
    4
   / \
  9   0
 / \
5   1
输出: 1026
解释:
从根到叶子节点路径 4->9->5 代表数字 495.
从根到叶子节点路径 4->9->1 代表数字 491.
从根到叶子节点路径 4->0 代表数字 40.
因此,数字总和 = 495 + 491 + 40 = 1026.

思路:网上大神的代码,原文链接:https://blog.csdn.net/DERRANTCM/article/details/47678205

这个代码感觉有点奇怪。。。。。是回溯的思想但是不太懂是怎么运行的。这个代码的执行时间也是最短的。

在这里补充一下递归和回溯的思想。原文链接:https://blog.csdn.net/zyh2525246/article/details/79718296

递归
递归是指函数/过程/子程序在运行过程中直接或间接调用自身而产生的重入现象。

运用递归的条件:
1. 子问题须与原始问题为同样的事,且更为简单;
2. 不能无限制地调用本身,须有个出口,化简为非递归状况处理。(递归结束条件)

回溯
回溯也称试探法,它的基本思想是:从问题的某一种状态(初始状态)出发,搜索从这种状态出发所能达到的所有“状态”,当一条路走到“尽头”的时候(不能再前进),再后退一步或若干步,从另一种可能“状态”出发,继续搜索,直到所有的“路径”(状态)都试探过。这种不断“前进”、不断“回溯”寻找解的方法,就称作“回溯法”。
这两个程序都是用的回溯的思想。从根节点开始出发,一直搜索到叶子结点,然后返回,直到遍历完所有的路径。

回溯是一种算法思想,可以用递归实现。通俗点讲回溯就是一种试探,类似于穷举

 

代码:

public class Solution {
    private int result = 0;
    // 记录总的结果
    private int num = 0;
    // 记根到叶子的数字
    public int sumNumbers(TreeNode root) {
        sum(root);
        return result;
    }
    private void sum(TreeNode root) {
        if (root != null) {
            num = num*10 + root.val;
            // 已经到了叶子结点了
            if (root.left == null && root.right == null) {
                result += num;
            }
            sum(root.left);
            sum(root.right);
            num /= 10;
        }
    }
}

我自己重新做了这个题,本来想的是用深度优先搜索来做,然后将每一条路径上的数字存储在StringBuilder中但是后面字符串转换为数字总是出错,之后参考了评论中的解法,将数据存放在另外一个栈中,直接存储数字。代码在下面,这个运行比较慢:

class Solution {
    public int sumNumbers(TreeNode root) {
        if(root==null)
            return 0;
        Stackstack=new Stack<>();
        Stack numStack = new Stack<>();
        stack.push(root);
        numStack.push(0);
        int sum=0;
        while(!stack.isEmpty()){
            TreeNode temp=stack.pop();
            Integer cur=numStack.pop()*10+temp.val;
          
            if(temp.left!=null){
                stack.push(temp.left);
                numStack.push(cur);
            }
            if(temp.right!=null){
                stack.push(temp.right);
                 numStack.push(cur);
                
            }
            
            if(temp.left==null&&temp.right==null){
                
                sum+=cur;
            }
        }
        return sum;
    }
}

执行最快的代码:

最快的代码也是回溯的思想,只不过写法不一样。使用一个二维数组,一个存放到当前节点为止的数据和,另一个存放总的结果和。

class Solution {
    public int sumNumbers(TreeNode root) {
        if(root == null) return 0;
        int[] sum = new int[2];
        generateNumbers(sum,root);
        return sum[1];
    }
    
    
    public void generateNumbers(int[] sum,TreeNode root){
        if(root.left == null&& root.right == null){
            sum[1] +=  10*sum[0] + root.val;
            return;
        }
        
        if(root.left!= null){
            sum[0] = 10*sum[0]+root.val;
            generateNumbers(sum,root.left);
            sum[0] = (sum[0]-root.val)/10;
        }
        
        if(root.right!=null){
            sum[0] = 10*sum[0]+root.val;
            generateNumbers(sum,root.right);
            sum[0] = (sum[0]-root.val)/10;
        }
    }
}

你可能感兴趣的:(LeetCode笔记)