转载请注明出处:http://blog.csdn.net/ns_code/article/details/28113959

剑指offer上的最后一题了,一个递归函数调了一下午,才得到正确的结果。

题目描写叙述:

给定一棵树,同一时候给出树中的两个结点,求它们的最低公共祖先。

输入:

输入可能包括多个測试例子。
对于每一个測试案例,输入的第一行为一个数n(0<n<1000),代表測试例子的个数。
当中每一个測试例子包括两行,第一行为一个二叉树的先序遍历序列,当中左右子树若为空则用0取代,当中二叉树的结点个数node_num<10000。
第二行为树中的两个结点的值m1与m2(0<m1,m2<10000)。

输出:

相应每一个測试案例,
输出给定的树中两个结点的最低公共祖先结点的值,若两个给定结点无最低公共祖先,则输出“My God”。

例子输入:
2
1 2 4 6 0 0 7 0 0 5 8 0 0 9 0 0 3 0 0
6 8
1 2 4 6 0 0 7 0 0 5 8 0 0 9 0 0 3 0 0
6 12
例子输出:
2
My God

这类的题目,方法蛮多的,思路也不难理解,基本都是各种遍历的变种,主要是写代码,尤其基于递归的代码。

首先假设是二叉排序树自然不用说了,推断的一句就是该节点的值是否位于输入的这两个节点之间,能够用前序遍历来做。

假设是普通的树或者二叉树,解题思路是一样的,能够考虑前序遍历,得到两个路径,用链表或数组保存起来,然后找出两条路径的最后一个公共节点就可以。也能够后序遍历的方式,遍历到输入的节点时,将该节点及其后面遍历到的节点都保存到一个链表或数组中,然后找出两条路径的第一个公共机节点就可以。

以下採用的是前序遍历,并用数组保存路径的代码。

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h> typedef struct BTNode
{
struct BTNode *lchild;
struct BTNode *rchild;
int data;
}BTNode,*BTree; /*
前序遍历找出根节点到数据域为val的节点路径,保存在path数组中,
这里index是保存到path数组中的元素的下标,*len用来保存路径长度,
假设能找到val,则返回ture,找不到则返回false
*/
bool GetPreTraversePath(BTree pTree,int val,int *path,int index,int *len)
{
if(pTree == NULL)
{
*len = 0;
return false;
} path[index] = pTree->data;
if(pTree->data == val)
{
*len = index+1;
return true;
}
else
{
bool can;
can = GetPreTraversePath(pTree->lchild,val,path,index+1,len);
if(!can)
can = GetPreTraversePath(pTree->rchild,val,path,index+1,len);
return can;
}
} /*
获取两个路径的最后一个公共节点,
因为对树的先序遍历的结果中,前面一定有些节点同样,因此一定能找到最后一个同样节点
*/
int GetFirstCommonNode(int *path1,int len1,int *path2,int len2)
{
int shortLen = len1<len2 ? len1:len2;
int i;
for(i=0;i<shortLen;i++)
{
if(path1[i] != path2[i])
break;
}
return path1[i-1];
} /*
依据先序遍历序列创建二叉树,因为可能改变根节点的指向,因此传入BTNode的二级指针
*/
void CreateBTree(BTree *pRoot)
{
int data;
scanf("%d",&data);
if(data == 0)
*pRoot = NULL;
else
{
*pRoot = (BTree)malloc(sizeof(BTNode));
if(*pRoot == NULL)
exit(EXIT_FAILURE);
(*pRoot)->data = data;
(*pRoot)->lchild = NULL;
(*pRoot)->rchild = NULL;
CreateBTree(&((*pRoot)->lchild));
CreateBTree(&((*pRoot)->rchild));
}
} /*
销毁二叉树
*/
void DestroyBTree(BTree pRoot)
{
if(pRoot != NULL)
{
if(pRoot->lchild != NULL)
DestroyBTree(pRoot->lchild);
if(pRoot->rchild != NULL)
DestroyBTree(pRoot->rchild);
free(pRoot);
pRoot = NULL;
}
} int main()
{
int path1[10000];
int path2[10000]; int n;
while(scanf("%d",&n) != EOF)
{
int i;
for(i=0;i<n;i++)
{
BTree pRoot = NULL;
CreateBTree(&pRoot); int val1,val2;
scanf("%d %d",&val1,&val2); int len1,len2;
bool can1 = GetPreTraversePath(pRoot,val1,path1,0,&len1);
bool can2 = GetPreTraversePath(pRoot,val2,path2,0,&len2); if(can1 && can2)
printf("%d\n",GetFirstCommonNode(path1,len1,path2,len2));
else
printf("My God\n"); DestroyBTree(pRoot);
}
}
return 0;
}
/**************************************************************
    Problem: 1509
    User: mmc_maodun
    Language: C
    Result: Accepted
    Time:130 ms
    Memory:920 kb
****************************************************************/

PS:寻找路径的递归代码调了一个下午,总算搞定了,每次碰到关于树的问题,一般都是三种遍历方式的变种来实现,自然想到递推,有些写着非常easy,有些写着总非常纠结,尤其要返回bool变量的时候,还是太菜,回头要抽个时间把二叉树的递归实现的一些题目好好总结下。

【剑指offer】近期公共祖先的更多相关文章

  1. 【Java】 剑指offer(68) 树中两个结点的最低公共祖先

      本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 输入两个树结点,求它们的最低公共祖先. 思路 该题首先要和面试 ...

  2. 剑指Offer(第二版)面试案例:树中两个节点的最低公共祖先节点

    (尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/74612786冷血之心的博客) 剑指Offer(第二版)面试案例:树 ...

  3. 剑指Offer - 九度1509 - 树中两个结点的最低公共祖先

    剑指Offer - 九度1509 - 树中两个结点的最低公共祖先2014-02-07 01:04 题目描述: 给定一棵树,同时给出树中的两个结点,求它们的最低公共祖先. 输入: 输入可能包含多个测试样 ...

  4. 【剑指Offer面试编程题】题目1509:树中两个结点的最低公共祖先--九度OJ

    题目描述: 给定一棵树,同时给出树中的两个结点,求它们的最低公共祖先. 输入: 输入可能包含多个测试样例. 对于每个测试案例,输入的第一行为一个数n(0<n<1000),代表测试样例的个数 ...

  5. 剑指 Offer 68 - II. 二叉树的最近公共祖先 + 最近公共祖先(LCA)

    剑指 Offer 68 - II. 二叉树的最近公共祖先 Offer_68_2 题目详情 题解分析 java代码 package com.walegarrett.offer; /** * @Autho ...

  6. 剑指 Offer 68 - I. 二叉搜索树的最近公共祖先 + 二叉排序树 + 最近公共祖先

    剑指 Offer 68 - I. 二叉搜索树的最近公共祖先 Offer_68_1 题目描述 方法一:迭代法 由于该题的二叉树属于排序二叉树,所以相对较简单. 只需要判断两个结点是否在根节点的左右子树中 ...

  7. 剑指 Offer 68 - I. 二叉搜索树的最近公共祖先

    剑指 Offer 68 - I. 二叉搜索树的最近公共祖先 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q ...

  8. 剑指 Offer 68 - II. 二叉树的最近公共祖先

    剑指 Offer 68 - II. 二叉树的最近公共祖先 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q,最近 ...

  9. 剑指offer——树中两个节点的最低公共祖先

    代码来源与<剑指offer> 得到从根节点开始到输入的两个结点的两条,需要遍历两次树,每遍历一次的时间复杂度是O(n),得到的两条路径的长度在最差情况时是O(n),通常情况下两条路径的长度 ...

随机推荐

  1. JVM 性能调优实战之:使用阿里开源工具 TProfiler 在海量业务代码中精确定位性能代码

    本文是<JVM 性能调优实战之:一次系统性能瓶颈的寻找过程> 的后续篇,该篇介绍了如何使用 JDK 自身提供的工具进行 JVM 调优将 TPS 由 2.5 提升到 20 (提升了 7 倍) ...

  2. CCMoveTo 等函数理解

    CCMoveTo: 使用CCMoveTo action来让对象从右侧屏幕外移动到屏幕左侧.注意可以通过指定duration参数控制这一过程需要多久,这里我们随机给他2-4秒的时间. CCCallFun ...

  3. Android引用百度定位API第三方组件后导致其它.so文件无法正常加载的问题

    查看当前调试设备CPU架构的方法: adb.exe shell getprop ro.product.cpu.abi  (一般返回值为:armeabi-v7a) adb.exe shell getpr ...

  4. 仿酷狗音乐播放器开发日志十九——CTreeNodeUI的bug修复二(附源码)

    转载请说明原出处,谢谢 今天本来打算把仿酷狗播放列表的子控件拖动插入功能做一下,但是仔细使用播放列表控件时发现了几个逻辑错误,由于我的播放 列表控件是基于CTreeViewUI和CTreeNodeUI ...

  5. 马上着手开发Mac应用程序

    你是否想要开发 Mac 应用程序却又不知道从哪里入手?本路线图提供了 Mac 应用程序开发的绝佳起点,即使你已经是一个 iOS 开发专家,本路线图对你依然适用.Apple让开发应用程序和提交应用程序到 ...

  6. oracle检查点checkpoint信息

    1.关于checkpoint的概述 checkpoint是oracle在数据库一致性关闭.实例恢复和oracle基本操作中不可缺少的机制,包含以下相关的含义: A.检查点的位置(checkpoint ...

  7. JQuery WEB前段开发

    JQuery WEB前段开发 Jquery是继prototype之后又一个优秀的Javascript框架.它是轻量级的js库 ,它兼容CSS3,还兼容各种浏览器(IE 6.0+, FF 1.5+, S ...

  8. [Hive - Tutorial] Built In Operators and Functions 内置操作符与内置函数

    Built-in Operators Relational Operators The following operators compare the passed operands and gene ...

  9. Android JNI之JAVA调用C/C++层

    转载请声明:原文转自:http://www.cnblogs.com/xiezie/p/5929996.html 一.java调用本地函数的开发步骤: 1.编写本地方法的类(可以说是用来叙述本地方法的类 ...

  10. cos

    Apple过于封闭,没啥朋友,这家伙应该比较高傲,曾仅和Intel,IBM and so on..一起玩过!Google过于开放,狐朋狗友,友人泛滥,殃及ecosystem,弊端已显,祸水将至.COS ...