亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C > 正文

深入二叉樹兩個結點的最低共同父結點的詳解

2020-01-26 16:10:12
字體:
來源:轉載
供稿:網友
題目:二叉樹的結點定義如下:
復制代碼 代碼如下:

struct TreeNode
   {
              int m_nvalue;
             TreeNode* m_pLeft;
             TreeNode* m_pRight;
};

輸入二叉樹中的兩個結點,輸出這兩個結點在數中最低的共同父結點。
分析:求數中兩個結點的最低共同結點是面試中經常出現的一個問題。這個問題至少有兩個變種。
第一變種是二叉樹是一種特殊的二叉樹:查找二叉樹。也就是樹是排序過的,位于左子樹上的結點都比父結點小,而位于右子樹的結點都比父結點大。我們只需要從根結點開始和兩個結點進行比較。如果當前結點的值比兩個結點都大,則最低的共同父結點一定在當前結點的左子樹中。如果當前結點的值比兩個結點都小,則最低的共同父結點一定在當前結點的右子樹中。
第二個變種是樹不一定是二叉樹,每個結點都有一個指針指向它的父結點。于是我們可以從任何一個結點出發,得到一個到達樹根結點的單向鏈表。因此這個問題轉換為求兩個單向鏈表的第一個公共結點。
現在我們回到這個問題本身。所謂共同的父結點,就是兩個結點都出現在這個結點的子樹中。因此我們可以定義一函數,來判斷一個結點的子樹中是不是包含了另外一個結點。這不是件很難的事,我們可以用遞歸的方法來實現:
復制代碼 代碼如下:

/*
// If the tree with head pHead has a node pNode, return true.
// Otherwise return false.
*/
bool HasNode(TreeNode* pHead, TreeNode* pNode)
{
 if(pHead == pNode)
  return true;
 bool has = false;
 if(pHead->m_pLeft != NULL)
  has = HasNode(pHead->m_pLeft, pNode);
 if(!has && pHead->m_pRight != NULL)
  has = HasNode(pHead->m_pRight, pNode);
 return has;
}

我們可以從根結點開始,判斷以當前結點為根的樹中左右子樹是不是包含我們要找的兩個結點。如果兩個結點都出現在它的左子樹中,那最低的共同父結點也出現在它的左子樹中。如果兩個結點都出現在它的右子樹中,那最低的共同父結點也出現在它的右子樹中。如果兩個結點一個出現在左子樹中,一個出現在右子樹中,那當前的結點就是最低的共同父結點?;谶@個思路,我們可以寫出如下代碼:
復制代碼 代碼如下:

/*
// Find the last parent of pNode1 and pNode2 in a tree with head pHead
*/
TreeNode* LastCommonParent_1(TreeNode* pHead, TreeNode* pNode1, TreeNode* pNode2)
{
 if(pHead == NULL || pNode1 == NULL || pNode2 == NULL)
  return NULL;
 // check whether left child has pNode1 and pNode2
 bool leftHasNode1 = false;
 bool leftHasNode2 = false;
 if(pHead->m_pLeft != NULL)
 {
  leftHasNode1 = HasNode(pHead->m_pLeft, pNode1);
  leftHasNode2 = HasNode(pHead->m_pLeft, pNode2);
 }
 if(leftHasNode1 && leftHasNode2)
 {
  if(pHead->m_pLeft == pNode1 || pHead->m_pLeft == pNode2)
   return pHead;
  return LastCommonParent_1(pHead->m_pLeft, pNode1, pNode2);
 }
 // check whether right child has pNode1 and pNode2
 bool rightHasNode1 = false;
 bool rightHasNode2 = false;
 if(pHead->m_pRight != NULL)
 {
  if(!leftHasNode1)
   rightHasNode1 = HasNode(pHead->m_pRight, pNode1);
  if(!leftHasNode2)
   rightHasNode2 = HasNode(pHead->m_pRight, pNode2);
 }
 if(rightHasNode1 && rightHasNode2)
 {
  if(pHead->m_pRight == pNode1 || pHead->m_pRight == pNode2)
   return pHead;
  return LastCommonParent_1(pHead->m_pRight, pNode1, pNode2);
 }
 if((leftHasNode1 && rightHasNode2) || (leftHasNode2 && rightHasNode1))
  return pHead;
 return NULL;
}

接著我們來分析一下這個方法的效率。函數HasNode的本質就是遍歷一棵樹,其時間復雜度是O(n)(n是樹中結點的數目)。由于我們根結點開始,要對每個結點調用函數HasNode。因此總的時間復雜度是O(n^2)。
我們仔細分析上述代碼,不難發現我們判斷以一個結點為根的樹是否含有某個結點時,需要遍歷樹的每個結點。接下來我們判斷左子結點或者右結點為根的樹中是否含有要找結點,仍然需要遍歷。第二次遍歷的操作其實在前面的第一次遍歷都做過了。由于存在重復的遍歷,本方法在時間效率上肯定不是最好的。
前面我們提過如果結點中有一個指向父結點的指針,我們可以把問題轉化為求兩個鏈表的共同結點?,F在我們可以想辦法得到這個鏈表。我們在這里稍作變化即可:
復制代碼 代碼如下:

/*
// Get the path form pHead and pNode in a tree with head pHead
*/
bool GetNodePath(TreeNode* pHead, TreeNode* pNode, std::list<TreeNode*>& path)
{
 if(pHead == pNode)
  return true;
 path.push_back(pHead);
 bool found = false;
 if(pHead->m_pLeft != NULL)
  found = GetNodePath(pHead->m_pLeft, pNode, path);
 if(!found && pHead->m_pRight)
  found = GetNodePath(pHead->m_pRight, pNode, path);
 if(!found)
  path.pop_back();
 return found;
}

 由于這個路徑是從跟結點開始的。最低的共同父結點就是路徑中的最后一個共同結點:
復制代碼 代碼如下:

/*
// Get the last common Node in two lists: path1 and path2
*/
TreeNode* LastCommonNode
(
 const std::list<TreeNode*>& path1,
 const std::list<TreeNode*>& path2
 )
{
 std::list<TreeNode*>::const_iterator iterator1 = path1.begin();
 std::list<TreeNode*>::const_iterator iterator2 = path2.begin();  
 TreeNode* pLast = NULL;
 while(iterator1 != path1.end() && iterator2 != path2.end())
 {
  if(*iterator1 == *iterator2)
   pLast = *iterator1;
  iterator1++;
  iterator2++;
 }
 return pLast;
}

有了前面兩個子函數之后,求兩個結點的最低共同父結點就很容易了。我們先求出從根結點出發到兩個結點的兩條路徑,再求出兩條路徑的最后一個共同結點。代碼如下:
復制代碼 代碼如下:

/*
// Find the last parent of pNode1 and pNode2 in a tree with head pHead
*/
TreeNode* LastCommonParent_2(TreeNode* pHead, TreeNode* pNode1, TreeNode* pNode2)
{
 if(pHead == NULL || pNode1 == NULL || pNode2 == NULL)
  return NULL;
 std::list<TreeNode*> path1;
 GetNodePath(pHead, pNode1, path1);
 std::list<TreeNode*> path2;
 GetNodePath(pHead, pNode2, path2);
 return LastCommonNode(path1, path2);
}

這種思路的時間復雜度是O(n),時間效率要比第一種方法好很多。但同時我們也要注意到,這種思路需要兩個鏈表來保存路徑,空間效率比不上第一個方法。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产在线播放不卡| 尤物九九久久国产精品的特点| 中文字幕亚洲天堂| 欧美精品18videos性欧美| 欧美日韩国产限制| 欧洲亚洲免费在线| 亚洲xxxx18| 国产一区二区久久精品| 亚洲一区免费网站| 久久精品91久久久久久再现| 亚洲久久久久久久久久久| 国产成人精品优优av| 欧美国产精品va在线观看| 久久精品99国产精品酒店日本| 亚洲国产小视频在线观看| 国产精品女人网站| 亚洲精品福利资源站| 国产成人极品视频| 国产欧美韩国高清| 成人免费激情视频| 国产精品久久久久久av下载红粉| 成人精品福利视频| 久久精品99久久久香蕉| 欧美黑人一区二区三区| 欧美精品久久久久久久久久| 成人黄色免费看| 日韩成人在线视频| 最近2019中文字幕一页二页| 亚洲欧美一区二区三区四区| 亚洲精品欧美一区二区三区| 国产精品香蕉在线观看| 91国自产精品中文字幕亚洲| 欧美日韩午夜激情| 久久99视频精品| 精品性高朝久久久久久久| 伊人久久精品视频| 精品国产欧美一区二区三区成人| 亚洲精品国产拍免费91在线| 久久久久免费精品国产| 91精品国产高清自在线| 丝袜情趣国产精品| 欧美在线观看网站| 久久综合九色九九| 欧美电影《睫毛膏》| 色七七影院综合| 欧美激情一区二区三区久久久| 亚洲网站在线观看| 久久精品国产久精国产思思| 国产www精品| 亚洲精品大尺度| 亚洲精品www久久久| 456亚洲影院| 亚洲一区二区三区sesese| 国产日本欧美一区二区三区在线| 久久色精品视频| 夜色77av精品影院| 亚洲精品v天堂中文字幕| www.欧美精品| 亚洲成人激情在线| 亚洲福利视频专区| 国产精国产精品| 精品国产91久久久| 91av视频在线观看| 久久精品在线视频| 午夜精品理论片| 欧美夫妻性生活视频| 久久伊人色综合| 日韩成人久久久| 成人一区二区电影| 国产精品电影网| 国产免费一区视频观看免费| 亚洲欧洲午夜一线一品| xxxxx91麻豆| 欧美激情一区二区三区高清视频| 欧美日韩国产精品一区二区三区四区| 久久人体大胆视频| 日本精品一区二区三区在线播放视频| 欧美中文在线观看国产| 欧美日韩人人澡狠狠躁视频| 日韩精品中文字| 懂色av影视一区二区三区| 在线看片第一页欧美| 亚洲精品视频免费在线观看| 成人乱人伦精品视频在线观看| 成人黄色av播放免费| 欧美丝袜一区二区三区| 91福利视频网| 91在线免费视频| 538国产精品视频一区二区| 久久99精品久久久久久琪琪| 国产97在线视频| 久久精品小视频| 久久久久久久爱| 亚洲精选中文字幕| 狠狠做深爱婷婷久久综合一区| 久久久免费精品视频| 在线视频国产日韩| 国内精久久久久久久久久人| 欧美亚州一区二区三区| 97国产真实伦对白精彩视频8| 亚洲福利视频免费观看| 国产精品香蕉在线观看| 国产精品 欧美在线| 欧美激情视频一区二区| 欧美日韩国产一中文字不卡| 日韩av在线最新| www国产亚洲精品久久网站| 欧洲s码亚洲m码精品一区| 懂色av影视一区二区三区| 国产精品旅馆在线| 亚洲小视频在线观看| 国产精品91在线观看| 亚洲天堂网在线观看| 91在线色戒在线| 亚洲自拍欧美色图| 亚洲欧美国产视频| 日本精品久久久久影院| 黑人巨大精品欧美一区二区免费| 欧美激情三级免费| 久久久精品一区| 亚洲在线一区二区| 国产精品久久久久久av福利软件| 久久久久久91香蕉国产| 日韩精品久久久久久久玫瑰园| 97久久久免费福利网址| 上原亚衣av一区二区三区| 欧美日韩国产页| 日本中文字幕久久看| 日韩精品黄色网| 国产精品自拍偷拍视频| 日韩精品免费在线视频| 一区二区三区美女xx视频| 欧美成人午夜视频| 欧美黑人xxx| 4388成人网| 最新国产成人av网站网址麻豆| 日韩在线免费高清视频| 国产精品人人做人人爽| 亚洲激情 国产| 亚洲欧洲在线免费| 精品女厕一区二区三区| 久久影院资源站| 日韩精品免费电影| 中文字幕久精品免费视频| 色偷偷888欧美精品久久久| 日本19禁啪啪免费观看www| 91精品国产高清| 亚洲最大福利视频网站| 在线精品国产成人综合| 国模极品一区二区三区| 国产精品日韩电影| 国产精品视频在线观看| 国产精品日韩一区| 俺去亚洲欧洲欧美日韩| 欧美丝袜一区二区| 亚洲成人网在线| 久久久电影免费观看完整版| 国产一区二区在线播放| 黑人巨大精品欧美一区免费视频| 国产精品久久久久久av福利| 欧美一级电影免费在线观看| 国产成人精品亚洲精品| 欧美性猛交xxxx| 国产精品一区二区三区毛片淫片|