首先是第一题,从二叉树中找某条路径的数值和是否等于某个特定值,我最开始用的方法用一个返回栈的函数递归,每个叶子把值写进栈里,然后中间节点把下面叶子传来的栈和二为一,然后对栈里的每个值加上自己的值,最上层返回一个总栈然后在里面看有没有sum,这个方法虽然AC了,但是我在做第二题是发现了更好的方法,还是递归,把sum传入,然后每一个节点用sum减去自己的值传入下一层递归,如果到叶子节点减完后sum变成了0,则返回true。
public Stack<Integer> haspath(TreeNode t){
Stack<Integer> s = new Stack<Integer>();
if(t==null)return s;
Stack<Integer> s1 = haspath(t.left);
while (!s1.isEmpty()){
int i = s1.pop();
i=i+t.val;
s.push(i);
}
Stack<Integer> s2 = haspath(t.right);
while (!s2.isEmpty()){
int i = s2.pop();
i=i+t.val;
s.push(i);
}
if(t.left==null&&t.right==null)s.push(t.val);
return s;
}
public boolean hasPathSum(TreeNode root, int sum) {
Stack<Integer> s = haspath(root);
while (!s.isEmpty()){
int i =s.pop();
if(i==sum)return true;
}
return false;
}
第二题就比较麻烦,需要找到和等于sum的所有路径。第一题的第一种方法从栈里可以找到每个路径的开始叶子节点,我本想通过深度优先找到叶子节点,但是找到时栈里并不是从root到叶子的路径,会有节点丢失,所以要想其他办法。
public Stack<Integer> haspath(TreeNode t){
Stack<Integer> s = new Stack<Integer>();
if(t==null)return s;
Stack<Integer> s1 = haspath(t.left);
while (!s1.isEmpty()){
int i = s1.pop();
i=i+t.val;
s.push(i);
}
Stack<Integer> s2 = haspath(t.right);
while (!s2.isEmpty()){
int i = s2.pop();
i=i+t.val;
s.push(i);
}
if(t.left==null&&t.right==null)s.push(t.val);
return s;
}
public boolean hasPathSum(TreeNode root, int sum) {
Stack<Integer> s = haspath(root);
while (!s.isEmpty()){
int i =s.pop();
if(i==sum)return true;
}
return false;
}之后我用了第一题第二种思路,递归每个节点向下传sum减去自身值,每个叶子节点返回一个队列,每个路径开始叶子创建一个链表把自己加进去,把链表加入队列中,其他叶子向上传空队列即可,中间阶段把收到的队列合二为一如果队列中有链表,就把自己打入链表中,继续上传队列,最顶层返回的队列里即包括所有的路径链表
public Queue<LinkedList<Integer>> haspath2(TreeNode t, int v){
Queue<LinkedList<Integer>> s = new LinkedList<LinkedList<Integer>>();
if(t==null)return s;
if(t.left==null&&t.right==null&&v-t.val==0){
LinkedList<Integer> l=new LinkedList<Integer>();
l.add(t.val);
s.offer(l);
return s;
}
Queue<LinkedList<Integer>> s1=haspath2(t.left, v-t.val);
Queue<LinkedList<Integer>> s2=haspath2(t.right, v-t.val);
while (!s1.isEmpty()){
LinkedList<Integer> l=s1.poll();
l.addFirst(t.val);
s.offer(l);
}
while (!s2.isEmpty()){
LinkedList<Integer> l=s2.poll();
l.addFirst(t.val);
s.offer(l);
}
return s;
}
public List<List<Integer>> pathSum(TreeNode root, int sum) {
LinkedList<List<Integer>> a1 = new LinkedList<List<Integer>>();
if(root==null)return a1;
Queue<LinkedList<Integer>> q = haspath2(root, sum);
while (!q.isEmpty()){
a1.add(q.poll());
}
return a1;
}递归要学会运用参数向下传递和返回值向上传递,学会利用容器传递不固定长的数据
Update 2015/08/18: 上面的解法都不好,第一题直接往下找,找到了返回即可,至于第二题,上面的思路是可行的,然后当年我还不会回溯法,第二题是个典型的回溯法,上面的解法是当发现一个可用解后,用容器向上传,这样很麻烦,回溯法是用一个临时的容器储存,让发现解时复制一个容器存入结果中然后递归,递归完成后要回溯所以要清除每步的操作。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public void check(TreeNode root, int sum, LinkedList<Integer> tmp, List<List<Integer>> res){
if (root == null)
return;
tmp.add(root.val);
if (sum - root.val == 0 && root.left == null && root.right == null){
res.add(new LinkedList(tmp));
}
check(root.left, sum - root.val, tmp, res);
check(root.right, sum - root.val, tmp, res);
tmp.remove(tmp.size() - 1);
}
public List<List<Integer>> pathSum(TreeNode root, int sum) {
List<List<Integer>> res = new LinkedList<List<Integer>>();
LinkedList<Integer> tmp = new LinkedList<Integer>();
check(root, sum, tmp, res);
return res;
}
}
本文详细介绍了如何使用递归和回溯法解决二叉树中寻找路径和等于特定数值的问题。包括两种方法:一种是通过栈记录路径和,另一种则是直接递归减去节点值直至叶子节点,最后使用队列收集所有满足条件的路径。重点讨论了参数传递、容器使用以及如何优化算法以避免重复计算。

被折叠的 条评论
为什么被折叠?



