[剑指offer]面试题第[68-2]题[Leetcode][第236题][JAVA][二叉搜索树的最近公共祖先][递归]
【問題描述】[中等]
235/68-1 搜索二叉樹 236/68-2 二叉樹
【解答思路】
遞歸
時(shí)間復(fù)雜度:O(N) 空間復(fù)雜度:O(N)
情況 1. , 2. , 3. , 4. 的展開寫法如下。
class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {if(root == null || root == p || root == q) return root;TreeNode left = lowestCommonAncestor(root.left, p, q);TreeNode right = lowestCommonAncestor(root.right, p, q);if(left == null && right == null) return null; // 1.if(left == null) return right; // 3.if(right == null) return left; // 4.return root; // 2. if(left != null and right != null)} }優(yōu)化版
class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {if(root == null || root == p || root == q) return root;TreeNode left = lowestCommonAncestor(root.left, p, q);TreeNode right = lowestCommonAncestor(root.right, p, q);if(left == null) return right;if(right == null) return left;return root;} }注釋版
//方法二:后序遍歷,先左子樹后右子樹最后root,從底至頂回溯,代碼簡(jiǎn)單,但是分析起來復(fù)雜;//當(dāng)root==null時(shí),說明當(dāng)前路徑?jīng)]有找到p或者q//當(dāng)root==p||root==q,假設(shè)先找到的是節(jié)點(diǎn)p://則繼續(xù)從找到的節(jié)點(diǎn)p開始尋找另一個(gè)節(jié)點(diǎn)q(迭代),當(dāng)?shù)诙€(gè)節(jié)點(diǎn)q也找到時(shí),進(jìn)行回溯,一開始回溯時(shí),會(huì)一直保持單側(cè)子樹不為null的情況,但是注意這種情況,不是由于p,q均在當(dāng)前單側(cè)子樹造成的,當(dāng)前回溯過程的單側(cè)子樹內(nèi)只有一個(gè)q;//繼續(xù)回溯,當(dāng)回溯至一個(gè)節(jié)點(diǎn)root時(shí),節(jié)點(diǎn) p,q在節(jié)點(diǎn)root的異側(cè),即雙側(cè)子樹均不為null時(shí),節(jié)點(diǎn) root即為最近公共祖先。//返回root,后續(xù)則又會(huì)變?yōu)閱蝹?cè)子樹不為null,這時(shí)才是因?yàn)閜,q均在當(dāng)前單側(cè)子樹造成的;public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {//root=null,返回root說明這條路徑?jīng)]有找到p或者q;root=p||root=q時(shí)說明當(dāng)前找到了p或者q;if(root==null||root==p||root==q) return root;TreeNode left = lowestCommonAncestor(root.left,p,q);TreeNode right = lowestCommonAncestor(root.right,p,q);//后面是回溯過程,下面三個(gè)if語句可以交換順序,如果固定順序,則后面兩個(gè)if可以進(jìn)行簡(jiǎn)化//當(dāng)root的左子樹和右子樹都沒有p或者q時(shí),root不是p和q祖先,返回null;if(left==null&&right==null) return null;//基于第一個(gè)if,這里的if可以簡(jiǎn)寫為if(right==null) return left;//這里root的右子樹沒有找到p或者q,left找到了p或者q,這里返回的left有兩種情況://1.未找到最近公共節(jié)點(diǎn)時(shí),即還在迭代階段,這里返回的left為找到的p(假設(shè)為p),即第一個(gè)if的return結(jié)果://若前面沒有找到q,則從p開始繼續(xù)進(jìn)行迭代,在二叉樹中剩余的節(jié)點(diǎn)中找到剩下的那個(gè)q; 若之前已經(jīng)找到了q,則開始返回,直到找到left!=null&&right!=null,即找到了最近公共祖宗;//2.找到最近公共節(jié)點(diǎn)時(shí),即處于返回階段,不需要再進(jìn)行迭代了,此時(shí)p,q在同一側(cè)子樹中,這里left為找到的最近公共節(jié)點(diǎn),即下面最后一個(gè)return的結(jié)果;if(left!=null&&right==null) return left;//基于第一個(gè)if,這里的if可以簡(jiǎn)寫為if(left==null) return right;//這里的分析和上面一個(gè)if類似;if(left==null&&right!=null) return right;return root;//即if(left!=null&&right!=null) return root;但注釋中的寫法會(huì)使得函數(shù)缺少return語句;}【總結(jié)】
1. 二叉樹遍歷
前序遍歷 先輸出當(dāng)前結(jié)點(diǎn)的數(shù)據(jù),再依次遍歷輸出左結(jié)點(diǎn)和右結(jié)點(diǎn)
中序遍歷 先遍歷輸出左結(jié)點(diǎn),再輸出當(dāng)前結(jié)點(diǎn)的數(shù)據(jù),再遍歷輸出右結(jié)點(diǎn)
后續(xù)遍歷 先遍歷輸出左結(jié)點(diǎn),再遍歷輸出右結(jié)點(diǎn),最后輸出當(dāng)前結(jié)點(diǎn)的數(shù)據(jù)
2. 對(duì)于二叉樹的題,開始可以用遞歸的思想去思考單 代碼簡(jiǎn)單 過程不簡(jiǎn)單
3. 相關(guān)題目[劍指offer]面試題第[68-1]題[Leedcode][JAVA][第235題][二叉搜索樹的最近公共祖先][遞歸][BFS]
作者:Krahets
轉(zhuǎn)載鏈接:https://leetcode-cn.com/problems/er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof/solution/mian-shi-ti-68-ii-er-cha-shu-de-zui-jin-gong-gon-7/
參考鏈接:https://leetcode-cn.com/problems/er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof/solution/mian-shi-ti-68-ii-javashi-xian-jian-zhi-offersi-lu/
總結(jié)
以上是生活随笔為你收集整理的[剑指offer]面试题第[68-2]题[Leetcode][第236题][JAVA][二叉搜索树的最近公共祖先][递归]的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NRedis-Proxy - 高性能中间
- 下一篇: 让Apache支持Wap网站