二叉树中两节点之间最短路径

折腾了一下午,在参考 liuyi1207164339帖子ethannnli的帖子的基础上搞定了这个问题。刚开始头真的大了,感觉有点超出能力范围了。分析了他们的思路,求解这个二叉树中两节点的最短路径这个问题可以分解为三个子问题:1.求出二叉树中两个节点p和q的最小公共祖先   2.分别求出最小公共祖先节点到p和q的路径  3.归并求出的两条路径
问题1求解可以参考: https://segmentfault.com/a/1190000003509399,ethannnli 采用了二分法和深度搜索两种方法求解。
问题2求解可以参考: http://blog.csdn.net/liuyi1207164339/article/details/50916687,采用深度搜索求出lca到p或者q的路径。
问题3求解比较简单,我是直接通过对前两步返回的字符串进行后处理。
以如下二叉树作为测试二叉树:

public class FindShortestPath {

	//查找指定节点的标记
	boolean bLeafIsFound = false;
	String path1;
	public String findPath(TreeNode root, Stack<Integer> path, TreeNode nodeToFind){
		
		if (root == null) {
			
			return null;
			
		}
		
		//将路径节点添加到栈中
		path.push(root.val);
		//如果到达了子节点
		if (!bLeafIsFound && root.val == nodeToFind.val) {
			
			//打印路径
			path1 = printPath(path);
			bLeafIsFound = true;
			return path1;
			
		}
		
		//查询左子树
		if (!bLeafIsFound && root.left != null) {
			
			findPath(root.left,path, nodeToFind);
			
		}
		
		//查询右子树
		if (!bLeafIsFound && root.right != null) {
			
			findPath(root.right, path, nodeToFind);
			
		}
		
		//如果没找到则弹栈
		if (!bLeafIsFound) {
			
			path.pop();
			
		}
		
		return path1 == null ? null : path1;
		
	}
	
	public String printPath(Stack<Integer> path){
		
		int len = path.size();
		
		String s = ""+ path.pop();
		
		for (int i = 1; i < len; i++) {
			
			if (path.peek() != null) {
				
				s += "->" + path.pop();

			}
						
		}
		
		System.out.println(s);
		
		return s;
		
		
	}
	
	public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q){
		
		//发现目标节点则通过返回值标记该子树发现了某个目标节点
		if (root == null || root == p || root == q) {
			
			return root;
			
		}
		
		//查看左子树中是否有目标节点,没有为null
		TreeNode left = lowestCommonAncestor(root.left, p, q);
		//查看右子树中是否有目标节点,没有为null
		TreeNode right = lowestCommonAncestor(root.right, p, q);
		//都不为空,则说明左右子树都有目标节点,则公共祖先就是本身。
		if (left != null && right != null) {
			
			return root;
			
		}
		
		return left == null ? right : left;
		
	}
	
	public void findPathOfTwoNode(TreeNode root,TreeNode p, TreeNode q){
		
		Stack<Integer> path1 = new Stack<Integer>();
		Stack<Integer> path2 = new Stack<Integer>();
		
		//寻找两个路径的交点,即最小公共祖先
		TreeNode lca = lowestCommonAncestor(root, p, q);
		//得到p节点的路径
		System.out.println("最小公共祖先节点" + lca.val + "和节点" + p.val + "之间的路径");
		String s1 = findPath(lca, path1, p);
		bLeafIsFound = false;//全局变量复位 
		//得到q节点的路径
		System.out.println("最小公共祖先节点" + lca.val + "和节点" + q.val + "之间的路径");
		String s2 = findPath(lca, path2, q);
		bLeafIsFound = false;//全局变量复位 
		
		//合并两条路径去掉重复的最小公共祖先
		String[] split = s2.split("->");
		String s3 = s1 + "->" + split[0];
		
		for (int i = 1; i < split.length; i++) {
			
			if (Integer.parseInt(split[i]) != lca.val) {
				
				s3 +="->" + split[i];
			}
			
		}
		
		
		System.out.println("归并后的路径为:" + s3);
		
	}
	
	public static void main(String[] args) {
		
		TreeNode node1 = new TreeNode(1);
		TreeNode node2 = new TreeNode(2);
		TreeNode node3 = new TreeNode(3);
		TreeNode node4 = new TreeNode(4);
		TreeNode node5 = new TreeNode(5);
		TreeNode node6 = new TreeNode(6);
		TreeNode node7 = new TreeNode(7);
		TreeNode node8 = new TreeNode(8);
		
		node1.left = node2;
		node1.right = node3;
		node2.left = node4;
		node3.left = node5;
		node3.right = node6;
		node4.right = node7;
		node6.left = node8;
		
		FindShortestPath findShortestPath = new FindShortestPath();
		findShortestPath.findPathOfTwoNode(node1, node7, node3);
		
		
	}
	
	
}

我使用节点7和节点3作为p和q,测试结果如下:

结果没有什么问题,刚开始学习算法,肯定存在很多不足之处,希望大家多提意见,共同进步!

  • 7
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值