二叉树树中和为某一值的路径,该题目是剑指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);
}
}
写到最后
最后,回顾一下使用递归解决问题的套路:
第一步:判断递归终止条件(如上面这道变形题,递归终止条件可能是在进一步递归的时候就确定了)
第二步:确定当前的操作
第三步:进行更深层次的递归
第四步:重置为原来的状态