騰訊精選50題算法【二叉搜索樹的最近公共祖先】

最近幾周摻雜着需求、以及一些瑣碎的事情,算法的學習一直都是默默的在搞,沒有造成文章。程序員

或許是我懶惰了;或許是我鬆懈了;或許是我不重視了;可是,我還在。學習可能會由於工做推遲,但毫不會遲到,因此,還請各位放心,該有的都會到來。算法

以前也在有些羣裏看到算法的持續學習,我本身又找了一個方式來攻克LeetCode上的題目,先從騰訊精選練習(50題) 開始,以前有完成過一些,不過都是整合在ARTS打卡里,也沒細說。如今是一個系列,還有機會學習噠。微信

Algorithm LeetCode算法

235. 二叉搜索樹的最近公共祖先
(https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree/)學習

題目描述:給定一個二叉搜索樹,找到該樹中兩個指定節點的最近公共祖先。優化

百度百科中最近公共祖先的定義爲:「對於有根樹 T 的兩個結點p、q,最近公共祖先表示爲一個結點 x,知足 x 是 p、q 的祖先且 x 的深度儘量大(一個節點也能夠是它本身的祖先)。」code

6
   /    \
  2      8    
 / \    /  \
0   4  7    9
   / \
  3   5
示例1:
輸入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
輸出: 6 
解釋: 節點 2 和節點 8 的最近公共祖先是 6。
示例2:
輸入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
輸出: 2
解釋: 節點 2 和節點 4 的最近公共祖先是 2, 由於根據定義最近公共祖先節點能夠爲節點自己。

在題解以前,咱們仍是有必要知道二叉搜索樹是一顆什麼樣的樹,都有什麼特色。排序

二叉搜索樹(Binary Search Tree),又(二叉查找樹,二叉排序樹)它或者是一顆空樹,或者是具備下列性質的二叉樹:遞歸

  1. 若它的左子樹不空,則左子樹上全部結點的值均小於它的根結點的值;
  2. 若它的右子樹不空,則右子樹上全部結點的值均大於它的根結點的值;
  3. 它的左、右子樹分別爲二叉排序樹。

最近公共祖先: 是距離兩個節點最近的公共祖先節點。在這裏最近考慮的是節點的深度。leetcode

好比,在咱們這顆二叉樹中開發

  1. 若是p是2,q是8的狀況,分別在跟節點的左右兩邊,則最近的公共節點就是他們的根節點,即6;
  2. 若是p是2,q是7的狀況,由於仍是分別在6這個根節點的左右兩邊,那最近的公共節點仍是6;
  3. 若是p是2,q是4的狀況,2和4在節點2的右子樹上,即最小公共節點就是2本身了(一個節點也能夠是它本身的祖先)
  4. 若是p是2,q是0的狀況,2和0在節點2的左子樹上,即最小公共節點仍是2本身

好了,搞清楚了各類狀況,接下來的解法確定就難不倒咱們了。寫代碼是創建在思路清晰的基礎上,對吧。

解法:遞歸

  1. 從根節點開始遍歷
  2. 假若p和q都在右子樹上,則以右孩子爲根節點繼續1的操做
  3. 假若p和q都在左子樹上,則以左孩子爲根節點繼續1的操做
  4. 若是步驟2和步驟3均不成立,則說明咱們已經找到答案

將二叉樹構建完成:

// 將二叉樹構建完成
public static void main(String[] args) {
    TreeNode treeNode = new TreeNode(6);
    treeNode.left = new TreeNode(2);
    treeNode.left.left = new TreeNode(0);
    treeNode.left.right = new TreeNode(4);
    treeNode.left.right.left = new TreeNode(3);
    treeNode.left.right.right = new TreeNode(5);
        
    treeNode.right = new TreeNode(8);
    treeNode.right.left = new TreeNode(7);
    treeNode.right.right = new TreeNode(9);
        
    TreeNode treeNode2 = lowestCommonAncestor(treeNode, new TreeNode(2), new TreeNode(8));
    System.out.println(treeNode2);
}

遞歸查找二叉樹:

public static TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    int parent = root.val;
        
    int pValue = p.val;
        
    int qValue = q.val;
        
    // 若是兩個值都大於跟節點,則從右子樹查找
    if (pValue > parent &&qValue > parent) {
        return lowestCommonAncestor(root.right, p, q);
    // 若是兩個值都小於跟節點,則從左子樹查找
    } else if (pValue < parent && qValue < parent) {
        return lowestCommonAncestor(root.left, p, q);
    // 上述兩種狀況均沒有,則獲得答案
    } else {
        return root;
    }     
}

這裏僅僅舉例說明了經過遞歸的方式來解題,基本上也都能解決二叉樹相關的問題。可是,就這樣就夠了嗎?其實並無,二叉樹也有本身的特性,有時候是不須要經過遞歸來解決的。

在咱們這個題解裏,時間複雜度是O(N),空間複雜度是O(N),時間複雜度沒辦法了,N是節點中的個數,在最壞的狀況下咱們是須要訪問全部的節點,可是咱們能夠優化空間複雜度。

遞歸的時候,額外空間主要是棧產生的,N就是二叉樹的高度,最壞狀況下就是訪問全部的,可是咱們能夠經過另外一種方式來優化,空間複雜度能夠達到O(1)。歡迎在留言區和我互動,至於寫法,我會在知識星球給出,加入星球的小夥伴直接去看就行啦。

結語

二叉搜索樹,算是對二叉樹的一個延伸了,可是呢,解題的思路仍是大同小異,無非就是二叉搜索樹更加有本身的特色,咱們操做起來反而會目的性更明確一些,也更好去理解。

LeetCode真的是一個好的學習社區,不管在誰的眼裏,都是學習算法的好去處。小編也無數次的說過,算法就是一個持續學習的過程,只要持續學習,持續練習,持續寫代碼,你就能懂其中的解法,對於咱們程序員的思惟來講,是一個極大的提高,歡迎和你們一塊兒學習。

插播一條

彪悍一隻貓說過:他的不少次成爲第一的經歷,最主要的仍是來自於社羣的力量,若是沒有來自社羣的支持,他的推廣能力是有限的,要想拿第一,真的很難。

因此,作好一個品牌,須要社羣的力量,而後加上後期的IP推廣。萬事開頭難,我如今須要的仍是第一步,培養本身的社羣,創造屬於本身的一個小家庭,讓每一個人都有參與感,都能感覺到存在的價值。

因此,在創建微信羣的基礎上,我也把星球創建起來了,就是爲了和你們有更多的知識、職場等的交流。我我的還喜歡看球,還但願和你們一塊兒聊聊球,暢所欲言呢。

咱們的矩陣公衆號:奔跑吧攻城獅

簡介:專一於IT開發,和你聊聊職場話題,侃侃球,在休閒和知識的海洋裏遨遊

社羣slogan:社羣是小家,成長靠你們;人人共參與,攜手圖雙贏

我的slogan:當你的才華還沒法撐起你的野心時候,那應該靜下心來好好學習

相關文章
相關標籤/搜索