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

错误解法(题目要求只需要从上到下的某一段,而不是从根节点开始,这个错误解法求的是从根节点到下面结点的距离,不符合题意,用先根遍历求和不如下面解法一的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;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值