手撕算法——二叉树中和为某一值的路径及变形

二叉树树中和为某一值的路径,该题目是剑指offer上的一道题目,第一次刷题的时候一次就过了,所以没有当回事,当我遇到一个该题目的变形题的时候却一直通过不了,发现自己还是眼高手低,因此重新总结和记录一下。

二叉树中和为某一值的路径

题目描述

面试题34. 二叉树中和为某一值的路径
输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。
示例:
给定如下二叉树,以及目标和 sum = 22,
在这里插入图片描述
返回:
在这里插入图片描述
分析: 寻找二叉树中和为某一值的路径,那么就是从根节点出发找到它的叶子节点,二叉树遍历中只有先序遍历是从根节点出发,因此我们使用先序遍历来解决这道题。实现思路可以直接看代码。

代码实现

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<List<Integer>> pathSum(TreeNode root, int sum) {
       List<List<Integer> > lists=new ArrayList<>();
        //判非
        if(root==null){
            return  lists;
        }
        List<Integer> list=new ArrayList<>();
        countPathSum(root,sum,lists,list);
        return lists;
    }

    public void countPathSum(TreeNode root,int sum,List<List<Integer> > lists,List<Integer> list){
        //判断递归终止条件
        if(root==null){
            return;
        }
        //当前要执行的操作
        sum-=root.val;
        list.add(root.val);
        //如果该节点为叶子节点并且sum为0,则加入路径
        if(sum==0&&root.left==null&&root.right==null){
            lists.add(new ArrayList(list));
        }

        //更深层次的遍历
        countPathSum(root.left,sum,lists,list);
        countPathSum(root.right,sum,lists,list);

        //重置
        sum-=root.val;
        list.remove(list.size()-1);

    }
}

题目变形——获得路径的最高分

题目描述

这道题目明显是二叉树中和为某一路径的变形题,不同之处是这道题是N叉树,最高分是乘积。使用递归解题方法与上面相似。这里需要记录一下的是自己一直通不过的原因:
自己原来的代码是下面这样的:
也就是把重置原来的状态放到了for循环里面了,傻乎乎的认为for循环里面每次执行完递归都要重置状态,导致只能走到最左边的一条路径,其实对比上面的二叉树中和为某一值的路径就可以得到答案,for循环中每次去递归都是用的当前状态,因此需要在for循环外面重置状态

	for (int i = 0; i < edges.length; i++) {
			if (edges[i][0] == rootNode && !visited[edges[i][1]]) {
				helper(numsNode, edges[i][1], values, edges, visited, score);	
				//重新加载原来的属性
				score /= values[rootNode-1];
				visited[rootNode]=false;
			}	
		}
		
		

代码实现

package zhongxing;


public class Test1 {
	/*
	 *
	 给出了一颗有N个节点的树,索引从1到N,树的每个节点都有一个值。她想要追踪从根到其中一个叶子的路径。以便她能够获得该路径的最高得分。
	  路径的最高分定义为该路径中节点值的成绩 
	  输入: 
	 numNodes 表示树中节点数的整数 
	 rootNode 表示树中根节点索引的整数 
	 values一个整数列表,表示树中各节点的值 
	 edges,一个整数列表,其中列表的每个元素包含树的一对边
	  
	 输出 返回一个整数,表示可能的最大得分
	 
	 解决思路:可以使用深度优先搜索 从根节点出发 进行深度优先搜索
	 
	 */
	private static int maxScore;

	public static int find(int numsNode, int rootNode, int[] values, int[][] edges) {

		boolean visited[] = new boolean[numsNode + 1];
		int res = 0;
		res = helper(numsNode, rootNode, values, edges, visited, 1);
		return res;
	}

	public static int helper(int numsNode, int rootNode, int[] values, int[][] edges, boolean[] visited,int score) {
		
		visited[rootNode] = true;
		score *= values[rootNode-1];
		maxScore = maxScore > score ? maxScore : score;

		for (int i = 0; i < edges.length; i++) {
			if (edges[i][0] == rootNode && !visited[edges[i][1]]) {
				helper(numsNode, edges[i][1], values, edges, visited, score);	
			}	
		}
		
		//重新加载原来的属性
		score /= values[rootNode-1];
		visited[rootNode]=false;

		return maxScore;
	}

	public static void main(String[] args) {
		int[] values = { 2, 4, 100, 30, 9 };
		int[][] edges = { { 1, 2 }, { 1, 3 }, { 2, 4 }, { 2, 5 } };
		int res = find(5, 1, values, edges);
		System.out.println(res);
	}

}

写到最后

最后,回顾一下使用递归解决问题的套路:
第一步:判断递归终止条件(如上面这道变形题,递归终止条件可能是在进一步递归的时候就确定了)
第二步:确定当前的操作
第三步:进行更深层次的递归
第四步:重置为原来的状态

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值