二叉树中的和为某一值的路径
2016-06-06 21:58
295 查看
一,问题描述
给定一棵二叉树 和 一个整数,打印出二叉树中结点值的和为给定的整数的所有路径。注意:路径是指:从二叉树的根结点开始的,往下一直到叶子结点过程中 所经过的结点(包括根结点(起点)和叶子结点(终点))。
其中,关于二叉树相关知识可参考:二叉查找树的递归实现及递归分析(http://www.cnblogs.com/hapjin/p/5390451.html)
二,算法分析
应用了递归的先序遍历。先序遍历每个结点,将先序遍历的每个结点的和相加,相加的结果是给定的整数,则找到一条路径并打印之。
定义一个整型变量currentSum,保存当前访问到的路径上的结点之和;定义一个栈用来保存当前的路径。为什么用栈?因为这样可以与递归的先序遍历同步。
用了栈之后,如何打印路径?JAVA的LinkedList类的 descendingIterator()方法返回一个可以逆序遍历链表的迭代器。
结点中的值,即可以为正数 也可以为负数吗?答案是可以。因为,路径必须是从根到叶子结点,且整个递归调用会一直调用到叶子后才会返回。
代码实现如下:
可以看出:上面的代码是一个二叉树的先序遍历的典型应用!第9,10行表示:访问根结点[然后进行了一系列的处理(12-19行)];第21、22行表示访问根的左子树;第23、24行表示访问根的右子树。
当遍历到叶子结点时,在第26行,保存路径的栈会 pop,这相当于路径的回退。
三,扩展
如果给定的树中的结点值都是正数,且路径只需要从根结点开始,路径的终点不一定是叶子结点
这里,当currentSum > expectedSum时,就不需要再向下进行递归调用了。因为,结点值都是正数,再向下递归调用只会是currentSum越来越大。
比如,expectedSum为 13,当遍历到结点6时,currentSum=8+6=14 了,就不需要再向下进行遍历了。
如果expectedSum=14,那么遍历到6之后,也不需要再向下遍历了。总之,只有当currentSum 小于 expectedSum时,才需要向下进行遍历。代码实现如下:
完整代码如下:
给定一棵二叉树 和 一个整数,打印出二叉树中结点值的和为给定的整数的所有路径。注意:路径是指:从二叉树的根结点开始的,往下一直到叶子结点过程中 所经过的结点(包括根结点(起点)和叶子结点(终点))。
其中,关于二叉树相关知识可参考:二叉查找树的递归实现及递归分析(http://www.cnblogs.com/hapjin/p/5390451.html)
二,算法分析
应用了递归的先序遍历。先序遍历每个结点,将先序遍历的每个结点的和相加,相加的结果是给定的整数,则找到一条路径并打印之。
定义一个整型变量currentSum,保存当前访问到的路径上的结点之和;定义一个栈用来保存当前的路径。为什么用栈?因为这样可以与递归的先序遍历同步。
用了栈之后,如何打印路径?JAVA的LinkedList类的 descendingIterator()方法返回一个可以逆序遍历链表的迭代器。
结点中的值,即可以为正数 也可以为负数吗?答案是可以。因为,路径必须是从根到叶子结点,且整个递归调用会一直调用到叶子后才会返回。
代码实现如下:
public void findExpectedSumPath(BinaryNode root, int expectedSum){ if(root == null) return; LinkedList<BinaryNode> stack = new LinkedList<BinaryNode>(); int currentSum = 0; findExpectedSumPath(root, expectedSum, currentSum, stack); } private void findExpectedSumPath(BinaryNode root, int expectedSum, int currentSum, LinkedList<BinaryNode> stack){ currentSum += root.element; stack.push(root); // visit root boolean isLeaf = (root.left == null && root.right == null); if(currentSum == expectedSum && isLeaf){//print path Iterator<BinaryNode> it = stack.descendingIterator();//逆序遍历List(Stack) while(it.hasNext()) System.out.print(it.next().element + " "); System.out.println(); }//end if if(root.left != null)//visit left sub tree findExpectedSumPath(root.left, expectedSum, currentSum, stack); if(root.right != null)//visit right sub tree findExpectedSumPath(root.right, expectedSum, currentSum, stack); stack.pop();//当某结点左右孩子均为null时, 回退 }
可以看出:上面的代码是一个二叉树的先序遍历的典型应用!第9,10行表示:访问根结点[然后进行了一系列的处理(12-19行)];第21、22行表示访问根的左子树;第23、24行表示访问根的右子树。
当遍历到叶子结点时,在第26行,保存路径的栈会 pop,这相当于路径的回退。
三,扩展
如果给定的树中的结点值都是正数,且路径只需要从根结点开始,路径的终点不一定是叶子结点
这里,当currentSum > expectedSum时,就不需要再向下进行递归调用了。因为,结点值都是正数,再向下递归调用只会是currentSum越来越大。
比如,expectedSum为 13,当遍历到结点6时,currentSum=8+6=14 了,就不需要再向下进行遍历了。
如果expectedSum=14,那么遍历到6之后,也不需要再向下遍历了。总之,只有当currentSum 小于 expectedSum时,才需要向下进行遍历。代码实现如下:
public void findExpectedSumPath2(BinaryNode root, int expectedSum){ if(root == null) return; LinkedList<BinaryNode> stack = new LinkedList<BinaryNode>(); int currentSum = 0; findExpectedSumPath2(root, expectedSum, currentSum, stack); } private void findExpectedSumPath2(BinaryNode root, int expectedSum, int currentSum, LinkedList<BinaryNode> stack){ currentSum += root.element; stack.push(root); // boolean isLeaf = (root.left == null && root.right == null); if(currentSum == expectedSum){//print path Iterator<BinaryNode> it = stack.descendingIterator();//逆序遍历List(Stack) while(it.hasNext()) System.out.print(it.next().element + " "); System.out.println(); }//end if //当currentSum > expectedSum时 再往下递归没有意义了 if(currentSum < expectedSum){ if(root.left != null) findExpectedSumPath2(root.left, expectedSum, currentSum, stack); if(root.right != null) findExpectedSumPath2(root.right, expectedSum, currentSum, stack); } stack.pop();//当某结点左右孩子均为null时, 回退 }
完整代码如下:
import java.util.Iterator; import java.util.LinkedList; import java.util.Queue; public class ExpectedSumPath { private class BinaryNode{ int element; BinaryNode left; BinaryNode right; public BinaryNode(int ele) { element = ele; this.left = this.right = null; } } private BinaryNode root;//树根 public void insert(int element){ root = insert(element, root); } private BinaryNode insert(int element, BinaryNode root){ if(root == null) return new BinaryNode(element); if (element > root.element) root.right = insert(element, root.right); else if(element < root.element) root.left = insert(element, root.left); else ; return root; /** if(Math.random() > 0.5)//insert a node randomly in left nodes root.left = insert(element, root.left); else root.right = insert(element, root.right); return root; */ } public void printTree(BinaryNode root){ if(root == null) return; Queue<BinaryNode> queue = new LinkedList<>(); int current;//当前层 还未打印的结点个数 int next;//下一层结点个数 queue.offer(root); current = 1; next = 0; while(!queue.isEmpty()){ BinaryNode currentNode = queue.poll(); System.out.printf("%-4d", currentNode.element); current--; if(currentNode.left != null){ queue.offer(currentNode.left); next++; } if(currentNode.right != null){ queue.offer(currentNode.right); next++; } if(current ==0){ System.out.println(); current = next; next = 0; } } } public void findExpectedSumPath(BinaryNode root, int expectedSum){ if(root == null) return; LinkedList<BinaryNode> stack = new LinkedList<BinaryNode>(); int currentSum = 0; findExpectedSumPath(root, expectedSum, currentSum, stack); } private void findExpectedSumPath(BinaryNode root, int expectedSum, int currentSum, LinkedList<BinaryNode> stack){ currentSum += root.element; stack.push(root); boolean isLeaf = (root.left == null && root.right == null); if(currentSum == expectedSum && isLeaf){//print path Iterator<BinaryNode> it = stack.descendingIterator();//逆序遍历List(Stack) while(it.hasNext()) System.out.print(it.next().element + " "); System.out.println(); }//end if if(root.left != null) findExpectedSumPath(root.left, expectedSum, currentSum, stack); if(root.right != null) findExpectedSumPath(root.right, expectedSum, currentSum, stack); stack.pop();//当某结点左右孩子均为null时, 回退 } public void findExpectedSumPath2(BinaryNode root, int expectedSum){ if(root == null) return; LinkedList<BinaryNode> stack = new LinkedList<BinaryNode>(); int currentSum = 0; findExpectedSumPath2(root, expectedSum, currentSum, stack); } private void findExpectedSumPath2(BinaryNode root, int expectedSum, int currentSum, LinkedList<BinaryNode> stack){ currentSum += root.element; stack.push(root); // boolean isLeaf = (root.left == null && root.right == null); if(currentSum == expectedSum){//print path Iterator<BinaryNode> it = stack.descendingIterator();//逆序遍历List(Stack) while(it.hasNext()) System.out.print(it.next().element + " "); System.out.println(); }//end if //当currentSum > expectedSum时 再往下递归没有意义了 if(currentSum < expectedSum){ if(root.left != null) findExpectedSumPath2(root.left, expectedSum, currentSum, stack); if(root.right != null) findExpectedSumPath2(root.right, expectedSum, currentSum, stack); } stack.pop();//当某结点左右孩子均为null时, 回退 } public static void main(String[] args) { ExpectedSumPath tree = new ExpectedSumPath(); int[] elements = {20,18,4,19,22}; for (int i : elements) { tree.insert(i); } tree.findExpectedSumPath2(tree.root, 42); } }
相关文章推荐
- 20160606 码农头条日报
- 09-Hive查询操作Distributed by 和sort by
- Java Enumeration接口
- 机器学习自学指南
- 网页爬虫抓取js动态渲染数据
- ZOJ 3435 Ideal Puzzle Bobble(gcd(i,j,k)=1/莫比乌斯反演)
- html5 窗口之间的通信
- ToolBar工具条的简单使用
- RecyclerView 解析(三)
- 图像情感识别
- 动态规划学习
- MATLAB中为控件(uicontrol)绑定Callback函数(回调函数)
- 进程与线程共享的内容整理
- 看懂信息检索和网络数据挖掘领域论文的必备知识总结
- android之外部文件存储和读取
- 年轻人能为世界做什么
- android 消息处理机制
- 经典排序算法 - 快速排序Quick_sort
- leetcode 191. Number of 1 Bits
- java笔记2