首页 > 试题广场 >

给定一颗二叉树,以及其中的两个node(地址均非空),要求给

[问答题]
给定一颗二叉树,以及其中的两个node(地址均非空),要求给出这两个node的一个公共父节点,使得这个父节点与两个节点的路径之和最小。描述你程序的最坏时间复杂度,并实现具体函数,函数输入输出请参考如下的函数原型:
C++函数原型:
strucy TreeNode{
     TreeNode* left;   //指向左子树
     TreeNode* right;   //指向右子树
     TreeNode* father;   //指向父亲节点
};
TreeNode* LowestCommonAncestor(TreeNode* first,TreeNode* second){
}

推荐
由于有父节点指针,这道题目的难度一下子就降低了许多。

思路一:我们首先找到两个节点的高度差,然后从较靠近根结点的一层开始向上找,若父节点为同一节点则该节点为解。
int getHeight(TreeNode *node) {
    int height = 0;
    while (node) {
        height++;
        node = node->parent;
    }
    return height;
}

TreeNode* LowestCommonAncestor(TreeNode* first,TreeNode* second) {
    int height1 = getHeight(first), height2 = getHeight(second), diff = height1 - height2;
    if (diff < 0) {
        diff = -diff;
        while(diff--) {
             second = second->parent;
        }
    } else {
        while(diff--) {
            first = first->parent;
        }
    }
    while (first != second) {
        first = first->parent;
        second = second->parent;
    }
    return first;
}

思路二:若允许浪费空间,那么可以用两个Stack来存储从first和second到根结点的各个节点,然后出栈时比较地址是否一致,最后一个地址一致的节点为解。

两种方法最坏时间复杂度均为O(n)。
编辑于 2015-01-31 12:00:18 回复(9)
思路:既然每个节点都有指向父节点的指针,那么直接从给定的两个结点开始,向上找!
使得这个父节点与两个节点的路径之和最小,这就表明找的是最低公共祖先。
这个题目就转化为:求两个链表的第一个公共结点。
发表于 2015-08-07 10:20:52 回复(2)
简化的LCA;
因为有父节点,所以可以向上遍历。
  1. 将两个节点到根节点的路径压栈,然后依次比较,求最后一个公共的节点(需额外开销空间);
  2. 分布求两个节点的深度,然后较深节点向上遍历到和较浅节点的同一层。然后一起向上遍历,比较parent。
发表于 2015-08-10 19:02:13 回复(1)
/*问题描述:
写一个函数,输入一棵二叉树,树中每个结点存放了一个整数值,
函数返回这棵树中相差最大的两个结点间的差的绝对值。
解决思路:
定义两个参数n_max和n_min,遍历二叉树将结点元素的值与n_max和n_min比较并更新,最后返回n_max-n_min。*/
#include <iostream> 
#include <limits.h> 
#include <math.h> 
using namespace std;  
struct Node  
{  
    int val;  
    Node *left;  
    Node *right;  
    Node(int x) : val(x), left(NULL), right(NULL) {}  
};  
int maxValue(Node* root)  
{  
    if (root == NULL)  
        return 0;  
    int left = maxValue(root->left);  
    int right = maxValue(root->right);  
    int max = left>right ? left:right;  
    return root->val> max ? root->val : max;  
}  
int minValue(Node* root)  
{  
    if (root == NULL)  
        return 32767;  
    int left = minValue(root->left);  
    int right = minValue(root->right);  
    int min = left<right ? left:right;  
    return root->val < min ? root->val : min;  
}  
int diff(Node* root)  
{  
    return maxValue(root) - minValue(root);  
}
int main()  
{  
    Node* root0 = new Node(2);  
    Node* left01 = new Node(-5);  
    Node* right02 = new Node(-3);   
    Node* left11 = new Node(6);  
    Node* right12 = new Node(-2); 
    Node* left21 = new Node(-7);  
    Node* right22 = new Node(3);
    root0->left = left01;  
    root0->right = right02;
    left01->left =left11;
    left01->right=right12;
    right02->left=left21;
    right02->right=right22;
    cout << diff(root0) << endl;  
    return 0;  
}  

发表于 2018-06-10 11:48:45 回复(0)
int nodeHeight(TreeNode* node)
{
    int height = 0;
    while(node != NULL)
    {
        height++;
        node = node->father;
    }
}
TreeNode* LowestCommonAncestor(TreeNode* first, TreeNode* second)
{
    int diff = nodeHeight(first) - nodeHeight(second);
    if(diff > 0)
    {
        while(diff > 0)
        {
            first = first->father;
            diff--;
        }
    }
    else
    {
        while(diff < 0)
        {
            second = second->father;
            diff++;
        }
    }
    while(first != second)
    {
        first = first->father;
        second = second->father;
    }
    return first;
}

发表于 2016-03-12 16:13:45 回复(0)
class TreeNode:
    def __init__(self, x):
        self.left = None
        self.right = None
        self.father=None
def getheight(TreeNode):
    height=0
    while TreeNode:
        height+=1
        TreeNode=TreeNode.father
    return height
def lowestcommonancestor(TreeNode1,TreeNode2):
    height1=getheight(TreeNode1)
    height2=getheight(TreeNode2)
    if height1>height2:
        diff = height1 - height2
        while diff:
            TreeNode1 = TreeNode1.father
            diff -= 1
    else:
        diff = height2 - height1
        while diff:
            TreeNode2 = TreeNode2.father
            diff -= 1
    while TreeNode1!=TreeNode2:
        TreeNode1 = TreeNode1.father
        TreeNode2 = TreeNode2.father
    return TreeNode1
最坏时间复杂度为O(n)

编辑于 2018-04-09 16:40:15 回复(0)
public class FindFatherNode {
    public TreeNode findFather(TreeNode first,TreeNode second){
         int len1 = 0;
         int len2 = 0;
         TreeNode temp1 = first;
         TreeNode temp2 = second;
         while(temp1!=null){
             temp1 = temp1.father;
             len1++;
             
         }
         while(temp2!=null){
             temp2 = temp2.father;
             len2++;
             
         }
         int m = len1>len2?len2:len1;
         for(int i = 1;i<=m;i++){
             temp1 = first.father;
         }
         return temp1;
    }

}

发表于 2018-04-08 20:51:10 回复(0)
 
发表于 2018-03-16 21:02:55 回复(0)
strucy TreeNode{
     TreeNode* left;   //指向左子树
     TreeNode* right;   //指向右子树
     TreeNode* father;   //指向父亲节点
};
TreeNode* LowestCommonAncestor(TreeNode* first,TreeNode* second){
  set<TreeNode*> path;
  while (first->father){
   path.insert(first->father);
   first = first->father;
  }
  while (second->father){
    if (path.find(second->father){
       return second->father;
    }
  }
  return NULL;
}

发表于 2016-11-21 09:03:49 回复(0)
struct TreeNode{
     TreeNode* left;   //指向左子树
     TreeNode* right;   //指向右子树
     TreeNode* father;   //指向父亲节点
};
//将各自的父节点都放在栈里面,找到第一个不相同的结点。上一个结点即为所求
//特殊情况:1.根节点为最近公共结点(处于根节点的左右两侧)
//2.最近公共父节点为first与second两者之一
TreeNode* LowestCommonAncestor(TreeNode* first,TreeNode* second){
    stack<TreeNode*>stk1;
    stack<TreeNode*>stk2;
    while (first!= NULL) {
       stk1.push(first->father);
       first = first->father;
    }
     while (second!= NULL) {
       stk1.push(second->father);
       second= second->father;
    }
    int length = stk1.size() < stk2.size() ? stk1.size() : stk2.size();
    TreeNode* pResult = NULL;
    for (int i = 0; i < length; ++i) {
       TreeNode* pNode1 = stk1.top();
       TreeNode* pNode2 = stk2.top();
       if (pNode1 == pNode2) {
           stk1.pop();
           stk2.pop();
           pResult = pNode1;
        }
       else {
          return pResult;
    }
    return pResult;
   } 
}

发表于 2016-09-05 15:19:29 回复(0)
两个无环链表的第一个公共结点。特别地, 如果其中一个节点是另一个节点的祖先呢,那应该求得是链表的第二个公共节点
编辑于 2016-09-04 19:43:24 回复(0)
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.right = self.left = self.father = None

def lowesetCommaonAncestor(node1, node2):
    if not node1 or not node2:
        return None

    if node1 == node2:
        return node1

    if hasSubNode(node1, node2):
        return node1

    return lowesetCommaonAncestor(node1.father, node2)

def hasSubNode(root, child):
    if not root or not child:
        return False
    if root == child:
        return True

    return hasSubNode(root, child.parent)
发表于 2016-09-04 12:13:35 回复(0)
用JavaScript要怎么写...==
发表于 2016-09-04 10:58:55 回复(0)
解法一:不利用题中给定的parent指针,直接将本题看成求解两个节点的最近公共祖先问题,得到如下的答案:
TreeNode* LowestCommonAncestor(TreeNode* head,TreeNode* first,TreeNode* second)
{
	if(head==NULL|| head==first|| head==second)
		return head;
	TreeNode* left=LowestCommonAncestor(head->left,first,second);
	TreeNode* right=LowestCommonAncestor(head->right,first,second);
	if((left!=NULL)&&(right!=NULL))
	{
		return head;
	}
	return left!=NULL?left:right;
}

解法二:利用题中给定的parent指针,分别求出两个节点到根节点的路径,再求这两个路径的交点即可,得到答案如下:

int height(TreeNode* node)//求解节点的高度
{
	if(node==NULL)
		return 0;
	int h;
	while(node)
	{
		h++;
		node=node->father;
	}
	return h;
}
TreeNode* LowestCommonAncestor(TreeNode* first,TreeNode* second)
{
	int h1=height(first),h2=height(second);
	int differ=h1-h2;
	if(differ<0)
	{
		differ=differ*(-1);
		while(differ--)
		{
			second=second->father;
		}
	}
	else
	{
		while(differ--)
		{
			first=first->father;
		}
	}
	while(first!=second)
	{
		first=first->father;
		second=second->father;
	}
	return first;
}

发表于 2016-03-09 10:43:33 回复(0)
mark
发表于 2016-01-07 11:04:54 回复(0)
思路:
二层嵌套循环,外层向上遍历first,内层向上遍历second,并拿second与first比较是否相等,如果相等,那么就是最近的共同父节点,返回即可。

代码:
TreeNode* LowestCommonAncestor(TreeNode* first,TreeNode* second)
{
	if(first == NULL||second == NULL)
		return NULL;
	if(first == second)
	{
		return first;
	}
	if(first == second.father)
			return first;
	if(second == first.father)
			return second;
	TreeNode *tempFirst = first;
	TreeNode *tempSecond = second;

	while(tempFirst->father != NULL&&tempSecond->father!=NULL)
	{
		tempFirst = tempFirst->father;
		tempSecond = second;
		while(tempSecond->father != NULL)
		{
			if(tempSecond == tempFirst)
			{
				return tempFirst;
			}
			tempSecond = tempSecond->father;
		}		
	}
}

编辑于 2015-11-11 15:36:02 回复(0)
TreeNode * LowestCommonAncestor(TreeNode *first, TreeNode *second)
{
    TreeNode *pFirst = first;
    TreeNode *pSecond = second;
    intfirstLen = 1;
    intsecondLen = 1;
    while(pFirst -> father ! = NULL) {
        pFirst = pFirst -> father;
        ++firstLen;
    }
    while(pSecond -> father ! = NULL) {
        pSecond = pSecond -> father;
        ++secondLen;
    }
    pFirst = first;
    pSecond = second;
    intlongPath = firstLen - secondLen;
    for(inti = 0; i < longPath; ++i) {
        pFirst = pFirst -> father;
    }
    if(firstLen < secondLen) {
        for(inti = 0; i < longPath; ++i) {
            pSecond = pSecond -> father;
        }
    }
    while(pFirst != pSecond) {
        pFirst = pFirst -> father;
        pSecond = pSecond -> father;
    }
    returnpFirst;
}

对于具有n个节点二叉树的时间复杂度,最坏为O(n)。
编辑于 2015-10-08 14:59:58 回复(0)
参考解析:
思路一:我们首先找到两个节点的高度差,然后从较靠近根结点的一层开始向上找,若父节点为同一节点则该节点为解。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
intgetHeight(TreeNode *node) {
    intheight = 0;
    while(node) {
        height++;
        node = node->parent;
    }
    returnheight;
}
 
TreeNode* LowestCommonAncestor(TreeNode* first,TreeNode* second) {
    intheight1 = getHeight(first), height2 = getHeight(second), diff = height1 - height2;
    if(diff < 0) {
        diff = -diff;
        while(diff--) {
             second = second->parent;
        }
    } else{
        while(diff--) {
            first = first->parent;
        }
    }
    while(first != second) {
        first = first->parent;
        second = second->parent;
    }
    returnfirst;
}

思路二:若允许浪费空间,那么可以用两个Stack来存储从first和second到根结点的各个节点,然后出栈时比较地址是否一致,最后一个地址一致的节点为解。

两种方法最坏时间复杂度均为O(n)。
发表于 2015-08-27 20:53:01 回复(0)
用递归遍历first的父节点的另一个子数中是否存在second节点,不过就是时间复杂度有点高
bool Compare(TreeNode* tempNode, TreeNode* second)
{
	if (tempNode == second)
	{
		return true;
	}

	if (tempNode->left)
	{
		Compare(tempNode->left, second);
	}
	if (tempNode->right)
	{
		Compare(tempNode->right, second);
	}
}

TreeNode* LowestCommonAncestor(TreeNode* first,TreeNode* second)
{
	if (first == NULL && second == NULL)
	{
		return;
	}
	TreeNode* fatherNode = first->father;
	bool isExist = false;
	while (fatherNode != NULL)
	{
		if (first == fatherNode->left)
		{
			isExist = Compare(fatherNode->right, second);
		}
		else if (first == fatherNode->right)
		{
			isExist = Compare(fatherNode->left, second);
		}

		if (isExist)
		{
			return fatherNode;
		}
		else
		{
			fatherNode = fatherNode->father;
		}
	}
}

发表于 2015-08-25 15:55:17 回复(0)
	vector<TreeNode*> firstPath;
	vector<TreeNode*> secondPath;
	TreeNode* tmpNode = first;
	while (tmpNode->father != NULL)
	{
		firstPath.push_back(tmpNode);
		tmpNode = tmpNode->father;
	}
	tmpNode = second;
	while (tmpNode->father != NULL)
	{
		secondPath.push_back(tmpNode);
		tmpNode = tmpNode->father;
	}

	// 从后向前找到最近的父节点
	int firstIndex = firstPath.size() - 1;
	int secondIndex = secondPath.size() - 1;
	while (firstPath[firstIndex] == secondPath[secondIndex])
	{
		--firstIndex;
		--secondIndex;
	}
	return firstIndex[firstIndex + 1];

发表于 2015-08-11 21:23:12 回复(0)