您的位置:首页 > 其它

leetcode[Path Sum III]//待整理多种解法

2017-07-21 11:38 441 查看
错误解法(题目要求只需要从上到下的某一段,而不是从根节点开始,这个错误解法求的是从根节点到下面结点的距离,不符合题意,用先根遍历求和不如下面解法一的DFS来得简单,因为DFS每次弹栈,压栈的形式固定,而先根遍历需要连续压栈什么的,无法保证Stack<TreeNode>与Stack<Integer>的同步压栈与弹栈,这里先根遍历还有问题,下面解法一的DFS是正确的):

/**
* Definition for a binary tree node.
* public class TreeNode {
*     int val;
*     TreeNode left;
*     TreeNode right;
*     TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public int pathSum(TreeNode root, int sum) {
int count = 0;
Stack<Integer> stackInt = new Stack<>();//用一个Stack记录下根节点到每个节点的距离之和
Stack<TreeNode> stackTree = new Stack<>();

//采用深度优先遍历
if(root == null) return 0;
stackTree.push(root);

//System.out.println(root.val);

stackInt.push(root.val);
if(root.val == sum)//计数
count++;
TreeNode temp = root.left;

while(temp != null){//先压入左最左边那一路
stackTree.push(temp);

//System.out.println(temp.val);

int pop = stackInt.pop();
stackInt.push(temp.val + pop);//根节点到当前节点的值与其父结点有关
if((temp.val + pop) == sum)//计数
count++;
temp = temp.left;
}

while(!stackTree.isEmpty()){
temp = stackTree.pop();
temp = temp.right;
while(temp != null){
stackTree.push(temp);

//System.out.println(temp.val);

int pop = stackInt.pop();
stackInt.push(temp.val + pop);//根节点到当前节点的值与其父结点有关
if((temp.val + pop) == sum)//计数
count++;
temp = temp.left;
}
}

return count;
}
}


错误解法二(这种取出所有的路径的方式会多计数,因为多条路径可能有交叉部分,而满足条件的某一段刚好就是交叉部分,所以不对):

/**
* Definition for a binary tree node.
* public class TreeNode {
*     int val;
*     TreeNode left;
*     TreeNode right;
*     TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public int pathSum(TreeNode root, int sum) {
int count = 0;

//采用深度优先遍历,求出根节点到每一个叶节点的完整路径,再来筛选每一条路径中存在的段数
Stack<TreeNode> stackTree = new Stack<>();
Stack<ArrayList<Integer>> stackList = new Stack<>();//用于保存由根节点到每个结点的具体路径,因为弹栈后右子节点会丢失父结点的信息
ArrayList<ArrayList<Integer>> list = new ArrayList<>();//用于保存所有的路径
ArrayList<Integer> tempList = new ArrayList<>();//用于保存每条路径

if(root == null) return 0;
stackTree.push(root);

//System.out.println(root.val);
tempList.add(root.val);//在应该遍历打印的位置插入节点
stackList.push(new ArrayList<>(tempList));//需要新建,因为之后tempList会被修改

TreeNode temp = root.left;

while(temp != null){//先压入左最左边那一路
stackTree.push(temp);

//System.out.println(temp.val);

//需要新建,因为之后tempList会被修改
tempList = new ArrayList<>(stackList.peek());//通过父结点的list再插入,这里父结点没有弹出,就不弹栈
tempList.add(temp.val);//在应该遍历打印的位置插入节点
stackList.push(tempList);

if(temp.left == null && temp.right == null){//判断是否是叶节点
list.add(tempList);//如果是叶节点,则这条路径完结
}

temp = temp.left;
}

while(!stackTree.isEmpty()){
temp = stackTree.pop();

//需要新建,因为之后tempList会被修改
tempList = new ArrayList<>(stackList.pop());//通过父结点的list再插入,这里父结点弹出,需要弹栈
temp = temp.right;
while(temp != null){
stackTree.push(temp);

//System.out.println(temp.val);
tempList.add(temp.val);//在应该遍历打印的位置插入节点
stackList.push(tempList);

if(temp.left == null && temp.right == null){//判断是否是叶节点
list.add(tempList);//如果是叶节点,则这条路径完结
}

temp = temp.left;
}
}

//开始从所有路径中查找满足条件的段数
for(int i = 0; i < list.size(); i++){
tempList = list.get(i);

System.out.println(Arrays.asList(tempList).toString()); //打印每一条路径

for(int j = 0; j < tempList.size(); j++){//用两层循环来找段落数,因为可能出现在中间某一段
int tempSum = 0;//每一次中间某段要清零,因为实际求和是在最内层循环
for(int k = j; k < tempList.size(); k++){
tempSum += tempList.get(k);
System.out.println(tempSum);
if(tempSum == sum)
count++;
}
}
}

return count;
}
}

解法一:

/**
* Definition for a binary tree node.
* public class TreeNode {
*     int val;
*     TreeNode left;
*     TreeNode right;
*     TreeNode(int x) { val = x; }
* }
*/
public class Solution {
/*错误解法(题目要求只需要从上到下的某一段,而不是从根节点开始,这个错误解法求的是从根节点到下面结点的距离,不符合题意):*/
//这里改进错误解法一,采用嵌套的遍历,在遍历到一个结点时,将其视为根节点进行遍历即可

public int pathSum(TreeNode root, int sum) {//外层遍历
int count = 0;
Stack<TreeNode> stackTree = new Stack<>();

//采用深度优先遍历
if(root == null) return 0;
stackTree.push(root);

//System.out.println(root.val);
count += pathSumHelp(root, sum);

TreeNode temp = root.left;

while(temp != null){//先压入左最左边那一路
stackTree.push(temp);

//System.out.println(temp.val);
count += pathSumHelp(temp, sum);

temp = temp.left;
}

while(!stackTree.isEmpty()){
temp = stackTree.pop();
temp = temp.right;
while(temp != null){
stackTree.push(temp);

//System.out.println(temp.val);
count += pathSumHelp(temp, sum);

temp = temp.left;
}
}

return count;
}

private int pathSumHelp(TreeNode root, int sum){//内层遍历,这里弹出的结点不再参与,所以不会有错误解法二那种交叉重复的问题
int count = 0;
Stack<TreeNode> stackTree = new Stack<>();
Stack<Integer> stackInt = new Stack<>();

if(root == null) return 0;

stackTree.push(root);
stackInt.push(root.val);//直接在插入结点时就计算出根节点到该结点的距离,再判断一下
if(root.val == sum) count++;

//进行DFS遍历
while(!stackTree.isEmpty()){
TreeNode tempTree = stackTree.pop();
int pop = stackInt.pop();
//压入左结点
if(tempTree.left != null){
stackTree.push(tempTree.left);
stackInt.push(tempTree.left.val + pop);
if((tempTree.left.val + pop) == sum) count++;
}

//压入右结点
if(tempTree.right != null){
stackTree.push(tempTree.right);
stackInt.push(tempTree.right.val + pop);
if((tempTree.right.val + pop) == sum) count++;
}
}

return count;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: