Leetcode-687-最長(zhǎng)同值路徑

給定一個(gè)二叉樹(shù)咧栗,找到最長(zhǎng)的路徑,這個(gè)路徑中的每個(gè)節(jié)點(diǎn)具有相同值圆丹。 這條路徑可以經(jīng)過(guò)也可以不經(jīng)過(guò)根節(jié)點(diǎn)居凶。

注意:兩個(gè)節(jié)點(diǎn)之間的路徑長(zhǎng)度由它們之間的邊數(shù)表示虫给。

示例 1:

輸入:


              5
             / \
            4   5
           / \   \
          1   1   5

輸出:

2

示例 2:

輸入:

              1
             / \
            4   5
           / \   \
          4   4   5

輸出:

2

注意: 給定的二叉樹(shù)不超過(guò)10000個(gè)結(jié)點(diǎn)。 樹(shù)的高度不超過(guò)1000侠碧。


分析:

1.如果不仔細(xì)觀察抹估,很容易陷入到一個(gè)TreeNode誤區(qū),對(duì)于用java解答的小伙伴弄兜,在IDE中解這道題药蜻,很容導(dǎo)包 import javax.swing.tree.TreeNode;,結(jié)果發(fā)現(xiàn)替饿,這個(gè)TreeNode是個(gè)interface呀语泽,這怎么辦?難道要找它的實(shí)現(xiàn)子類视卢?一臉茫然踱卵。淡定,這個(gè)時(shí)候就需要考驗(yàn)審題能力了据过,在平臺(tái)給出的答案區(qū)上方給出了注釋狀態(tài)的一段代碼惋砂,不知道讀者有沒(méi)有留意到?

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

其實(shí)這個(gè)就是本題需要的TreeNode绳锅,當(dāng)我們?cè)谄脚_(tái)上提交答案的時(shí)候西饵,不需要定義這個(gè)class,平臺(tái)驗(yàn)收答案時(shí)是帶著這個(gè)實(shí)現(xiàn)的鳞芙;而當(dāng)我們?cè)贗DE上進(jìn)行編碼調(diào)試的時(shí)候眷柔,需要把這個(gè)TreeNode代碼拷貝到IDE中,解開(kāi)注釋积蜻。然后闯割,就可以正式開(kāi)始解題了。

2.我們來(lái)分析一下題目的關(guān)鍵點(diǎn)竿拆。
二叉樹(shù):一個(gè)節(jié)點(diǎn)只有兩個(gè)子節(jié)點(diǎn)宙拉,左和右。
路徑:節(jié)點(diǎn)與節(jié)點(diǎn)之間的連線就是一條路徑
同值路徑:節(jié)點(diǎn)和與子節(jié)點(diǎn)或者父節(jié)點(diǎn)之間的值相同丙笋,那么這就是一條同值路徑谢澈,本題求的就是這個(gè)最大值。
邊數(shù):可以理解為題目示例中連接節(jié)點(diǎn)的直線御板。

3.這一類問(wèn)題梳庆,需要用遞歸的方法解決画髓。在二叉樹(shù)中纵顾,只能從根節(jié)點(diǎn)向下遞歸調(diào)用串慰,可以通過(guò)root.left和root.right的方法得到兩個(gè)子節(jié)點(diǎn)的TreeNode對(duì)象,由此一層一層遞歸調(diào)用下去,直到最底端的葉節(jié)點(diǎn)钉答。

4.第一個(gè)可能遇到的坑:如果當(dāng)前節(jié)點(diǎn)與左節(jié)點(diǎn)的值不同础芍,那么左邊的同值路徑就會(huì)斷掉,同理数尿,如果和右節(jié)點(diǎn)值不同仑性,右邊的同值路徑就會(huì)斷掉。一旦斷掉右蹦,那么當(dāng)前節(jié)點(diǎn)的同值路徑值就應(yīng)該清零诊杆。

5.第二個(gè)可能遇到的坑:如果當(dāng)前節(jié)點(diǎn)與子節(jié)點(diǎn)的值不同,那么從子節(jié)點(diǎn)連過(guò)來(lái)的同值路徑就斷掉了何陆,而如果當(dāng)前節(jié)點(diǎn)和父節(jié)點(diǎn)的值相同晨汹,需要注意,會(huì)從本節(jié)點(diǎn)向父節(jié)點(diǎn)連一個(gè)新的同值路徑甲献,與從子節(jié)點(diǎn)來(lái)的同值路徑無(wú)關(guān)宰缤,不可累加。本題求解的是多條同值路徑中最長(zhǎng)的那條晃洒。

6.第三個(gè)可能遇到的坑:先看下圖,這是平臺(tái)在驗(yàn)證答案時(shí)給出的測(cè)試用例朦乏。


平臺(tái)測(cè)試用例.png

看圖球及,這個(gè)二叉樹(shù)的最大同值路徑就是由根節(jié)點(diǎn)26組成的路徑,從根節(jié)點(diǎn)開(kāi)始呻疹,能連起來(lái)的吃引,值為26的節(jié)點(diǎn)一共是6個(gè),它們之間的連線一共是5條刽锤,那么答案就是5嗎镊尺?NONO,平臺(tái)的期望值是4并思,明白了嗎庐氮?這里有一個(gè)隱含條件,同值路徑必須是單向的宋彼,就是用紙筆能一筆畫完的弄砍,不能倒退著連。


根據(jù)這些分析输涕,java解答如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int longestUnivaluePath(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int[] longestPath = new int[1];
        getUnivaluePathCount(root, longestPath);
        return longestPath[0];
    }

    private int getUnivaluePathCount(TreeNode node, int[] longestPath) {
        int left = 0;
        if (node.left != null) {
            left += getUnivaluePathCount(node.left, longestPath);
            if (node.val == node.left.val) {
                /* 如果本節(jié)點(diǎn)和左節(jié)點(diǎn)值相同音婶,路徑能繼續(xù),再累加1 */
                left += 1;
            } else {
                /* 否則莱坎,就說(shuō)明左邊的路徑已經(jīng)斷開(kāi)衣式,本節(jié)點(diǎn)的左方向的單向路徑值清零 */
                left = 0;
            }
        }

        int right = 0;
        if (node.right != null) {
            right += getUnivaluePathCount(node.right, longestPath);
            if (node.val == node.right.val) {
                /* 如果本節(jié)點(diǎn)和右節(jié)點(diǎn)值相同,路徑能繼續(xù),再累加1 */
                right += 1;
            } else {
                /* 否則碴卧,就說(shuō)明右邊的路徑已經(jīng)斷開(kāi)弱卡,本節(jié)點(diǎn)的右方向的單向路徑值清零 */
                right = 0;
            }
        }
        int currentLongestPath;
        if (node.left != null && node.right != null && node.left.val == node.right.val) {
            /* 如果左右節(jié)點(diǎn)的值相同,那么可以相加連接起來(lái)螟深。但如果左右相同但和本節(jié)點(diǎn)值不同谐宙,那么left和right的值都是0 */
            currentLongestPath = left + right;
        } else {
            /* 否則,最大的路徑值只能是左右路徑的最大值 */
            currentLongestPath = Math.max(left, right);
        }
        if (currentLongestPath > longestPath[0]) {
            /* 最終返回的結(jié)果在這里界弧,每次遞歸都是以當(dāng)前節(jié)點(diǎn)為核心凡蜻,計(jì)算最大路徑值,在多次遞歸當(dāng)中垢箕,僅保留最大的值 */
            longestPath[0] = currentLongestPath;
        }
        /* 遞歸返回的是本節(jié)點(diǎn)與左右兩個(gè)子節(jié)點(diǎn)的同值路徑的最大值划栓,注意,如果本節(jié)點(diǎn)的值與左右節(jié)點(diǎn)的值都不同条获,那么返回的是0 */
        return Math.max(left, right);
    }
}

最后說(shuō)一下忠荞,本答案中的 int[] longestPath 用的java引用傳遞的特性,這并不是唯一的方法帅掘,還可以定義一個(gè)成員變量 private int longestPath; 來(lái)記錄所有的遞歸過(guò)程最大的同值路徑委煤,那樣會(huì)讓遞歸方法少一個(gè)參數(shù),在大量的遞歸調(diào)用過(guò)程中速度會(huì)更快修档。希望讀者們能學(xué)到這兩種方法碧绞,在今后的開(kāi)發(fā)中根據(jù)實(shí)際情況合理使用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末吱窝,一起剝皮案震驚了整個(gè)濱河市讥邻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌院峡,老刑警劉巖兴使,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異照激,居然都是意外死亡发魄,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門实抡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)欠母,“玉大人,你說(shuō)我怎么就攤上這事吆寨∩吞剩” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵啄清,是天一觀的道長(zhǎng)六水。 經(jīng)常有香客問(wèn)我俺孙,道長(zhǎng),這世上最難降的妖魔是什么掷贾? 我笑而不...
    開(kāi)封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任睛榄,我火速辦了婚禮,結(jié)果婚禮上想帅,老公的妹妹穿的比我還像新娘场靴。我一直安慰自己,他們只是感情好港准,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布旨剥。 她就那樣靜靜地躺著,像睡著了一般浅缸。 火紅的嫁衣襯著肌膚如雪轨帜。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天衩椒,我揣著相機(jī)與錄音蚌父,去河邊找鬼。 笑死毛萌,一個(gè)胖子當(dāng)著我的面吹牛苟弛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播阁将,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼嗡午,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了冀痕?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤狸演,失蹤者是張志新(化名)和其女友劉穎言蛇,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體宵距,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡腊尚,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了满哪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片婿斥。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖哨鸭,靈堂內(nèi)的尸體忽然破棺而出民宿,到底是詐尸還是另有隱情,我是刑警寧澤像鸡,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布活鹰,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏志群。R本人自食惡果不足惜着绷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望锌云。 院中可真熱鬧荠医,春花似錦、人聲如沸桑涎。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)石洗。三九已至幢泼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間讲衫,已是汗流浹背缕棵。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留涉兽,地道東北人招驴。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像枷畏,于是被迫代替她去往敵國(guó)和親别厘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • B樹(shù)的定義 一棵m階的B樹(shù)滿足下列條件: 樹(shù)中每個(gè)結(jié)點(diǎn)至多有m個(gè)孩子拥诡。 除根結(jié)點(diǎn)和葉子結(jié)點(diǎn)外触趴,其它每個(gè)結(jié)點(diǎn)至少有m...
    文檔隨手記閱讀 13,222評(píng)論 0 25
  • 第一章 緒論 什么是數(shù)據(jù)結(jié)構(gòu)? 數(shù)據(jù)結(jié)構(gòu)的定義:數(shù)據(jù)結(jié)構(gòu)是相互之間存在一種或多種特定關(guān)系的數(shù)據(jù)元素的集合渴肉。 第二章...
    SeanCheney閱讀 5,775評(píng)論 0 19
  • 因?yàn)橹熬蛷?fù)習(xí)完數(shù)據(jù)結(jié)構(gòu)了冗懦,所以為了保持記憶,整理了一份復(fù)習(xí)綱要仇祭,復(fù)習(xí)的時(shí)候可以看著綱要想具體內(nèi)容披蕉。 樹(shù) 樹(shù)的基本...
    牛富貴兒閱讀 6,879評(píng)論 3 10
  • 樹(shù) 記錄《劍指offer》中所有關(guān)于樹(shù)的題目,以及LeetCode中的相似題目乌奇。 相關(guān)題目列表 題目 樹(shù)是一種最常...
    wenmingxing閱讀 1,418評(píng)論 2 13
  • 他們都老啦没讲,我還年輕呢。有種瞌睡做了個(gè)長(zhǎng)夢(mèng)礁苗,其實(shí)只睡了一小會(huì)兒爬凑,醒來(lái)精力充沛時(shí)間還剩很多的賺到感。
    鼴吉吉閱讀 228評(píng)論 2 1