二叉樹的路徑處理問題

2021-09-02 22:28:13 字數 4764 閱讀 5443

路徑處理問題,實質上是使用樹的遍歷方法對樹進行遍歷,常常採用樹的先序遍歷方法對樹進行遍歷,對樹的先序遍歷方法稍加改動,改動先序遍歷時對中間節點的處理邏輯和對左右子樹的處理邏輯來實現題目的要求。

處理從根節點到每乙個葉子節點的路徑(即該二叉樹的所有路徑)上的所有節點,

例如leetcode257,問題描述及**如下:

問題描述:

給定乙個二叉樹,返回所有從根節點到葉子節點的路徑。

說明:葉子節點是指沒有子節點的節點。

示例:

輸入:1

/   \

2     3\5

輸出:["1->2->5", "1->3"]

解釋:所有根節點到葉子節點的路徑為: 1->2->5, 1->3

解決思路:從根節點開始進行中序遍歷,先處理中序遍歷時當前節點,將其入字串,字串中儲存著當前路徑中到目前為止的所有節點,然後處理左右子樹,在處理左右子樹時要判斷是否已經為葉子節點,如果已經到達葉子節點,則將當前字串入線性表,否則分別判斷左右子樹是否為空,遞迴處理其中不為空的子樹。

class solution 

private void paths(treenode root, listlist, string s)

//先序遍歷,處理中間節點

//要判斷是否已經到達一條路徑的盡頭,並在到達時將字串入線性表

//實質上還是對先序遍歷的稍加改動

s += root.val + " ";

if(root.left == null && root.right == null)

//先序遍歷,處理左右子樹

//處理邏輯為,左右子樹中任何乙個不為空,便遞迴處理該子樹

if(root.left != null)

if(root.right != null)

}}

2.leetcode 112路徑總和

問題描述:

給定乙個二叉樹和乙個目標和,判斷該樹中是否存在根節點到葉子節點的路徑,這條路徑上所有節點值相加等於目標和。

說明:葉子節點是指沒有子節點的節點。

示例:

給定如下二叉樹,以及目標和sum = 22

5

/ \4 8

/ / \

11 13 4

/ \ \

7 2 1

返回true, 因為存在目標和為 22 的根節點到葉子節點的路徑5->4->11->2

解決思路:寫乙個方法,該方法通過先序遍歷統計根節點到葉子節點的每一條路徑上節點和值等於目的值的數量,注意是從根節點開始,到葉子節點結束的所有路徑。

**:

class solution 

return (path(root, sum)>0) ? true : false;

}private int path(treenode root, int sum)

//先序遍歷,先處理中間節點

//關於result在這裡宣告的問題,需要說明一下,多多體會遞迴時在遞迴方法中宣告的變數所起到的所用

//result在遞迴方法中宣告,然後每次遞迴呼叫方法處理左右子樹返回的值都給result,方法最後返回result

//每次宣告的result都只在當前遞迴呼叫層有效,但由於將遞迴呼叫的方法返回值付給了當前層的reuslt

//這就使得最外層的result得到了層層往裡的遞迴呼叫的方法的返回值

//也可以反過來考慮,從葉子節點開始看,或者從找到的那個和為目的和的路徑的終節點看,該終結點返回result為1

//上一層的result會加上該終結點統計得到的1

//層層上傳,使得最終的result是1

int result = 0;

if(root.left == null && root.right == null && sum == root.val)

//先序遍歷,後遞迴處理左右子樹

//注意,此處將題目要求的求和變成,每次判斷當前節點值是否等於目的和值的減去前面所有節點和和值

//將求和變成減法

//sum - root.val

if(root.left != null)

if(root.right != null)

return result;

}}

3.leetcode 437路徑總和lll

問題描述:

給定乙個二叉樹,它的每個結點都存放著乙個整數值。

找出路徑和等於給定數值的路徑總數。

路徑不需要從根節點開始,也不需要在葉子節點結束,但是路徑方向必須是向下的(只能從父節點到子節點)。

二叉樹不超過1000個節點,且節點數值範圍是 [-1000000,1000000] 的整數。

示例:

root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8

10/ \

5 -3

/ \ \

3 2 11

/ \ \

3 -2 1

返回 3。和等於 8 的路徑有:

1. 5 -> 3

2. 5 -> 2 -> 1

3. -3 -> 11

解決思路:因為不要求起始節點為根節點,因此需要遍歷每乙個節點,從每乙個節點開始計算當前節點下的所有路徑值和是否為目的值,由於樹的遞迴操作的遍歷行,遍歷每乙個節點時,可以採用遞迴,先處理中間節點,然後遞迴處理左右子樹。需要寫乙個方法,該方法接受乙個節點、目的和值作為引數,返回該節點作為起始位置下和值為目的和值的路徑數。

**:

class solution 

return path(root, sum) + pathsum(root.left, sum) + pathsum(root.right, sum);

}//path先序遍歷

//path方法傳入當前節點及目的和值,判斷從當前節點開始有多少條路徑的和值等於目的值sum

private int path(treenode root, int sum)

//先序遍歷,先處理當前節點

int result = 0;

if(root.val == sum)

//先序遍歷,處理完當前節點後,處理左右子樹

result += path(root.left, sum - root.val);

result += path(root.right, sum - root.val);

return result;

}}

4.leetcode687題

問題描述:

給定乙個二叉樹,找到最長的路徑,這個路徑中的每個節點具有相同值。 這條路徑可以經過也可以不經過根節點。

注意:兩個節點之間的路徑長度由它們之間的邊數表示。

示例 1:

輸入:

5

/ \4 5

/ \ \

1 1 5

輸出:

2
示例 2:

輸入:

1

/ \4 5

/ \ \

4 4 5

輸出:

2
注意:給定的二叉樹不超過10000個結點。 樹的高度不超過1000。

解決思路:

思路一,先序遍歷,最容易想到的就是先序遍歷,或許是先序遍歷用習慣了?先寫乙個方法,該方法接受乙個節點作為引數,並計算出以該引數節點作為根節點的樹下,經過根節點的最長同值路徑,三種情況,左右子樹加根節點組成最長同值路徑,左子樹加根節點組成最長同值路徑,右子樹加根節點組成最長同值路徑;然後再另外乙個方法中遍歷這棵樹,在訪問每乙個節點時,呼叫上述方法,並傳入當前節點作為引數,計算當前節點下且經過當前節點的最長同值路徑,儲存遍歷過程中得到的最長同值路徑。寫出了上述思路的實現過程,但總是有測試用例出錯誤,排查了一上午也沒解決,上述思路的邏輯判斷過多,出錯誤後難以排查解決。

實際上,在做這道題時,產生上述思路的原因是習慣於使用先序遍歷,當先序遍歷不好解決問題的時候,應當考慮中序遍歷,和後序遍歷,一定要多思考先序、中序、後序遍歷的區別,及三種遍歷各自的遍歷路徑和處理順序。

思路二,後序遍歷,先處理左右子樹,然後處理中間節點,在處理中間節點的時候,判斷左右子樹的值是否與中間節點的值相同,若相同,則同值路徑加長,不相同,則說明左右子樹的同值路徑無法與中間節點合併加長,故清零;由於是後序遍歷,因此處理順序是從最底層開始向上層層處理。這個思路的處理方式是從下往上找同值路徑,並判斷左右子樹能否與當前連線成更大的同值路徑,已經連線好的下層同值路徑長度儲存在result中,在和中間節點連線新的同值路徑時,左右子樹的同值路徑必須是單向路徑(即左右子樹中的同值路徑不會是左中右這麼連線的),因此find返回值為left與right中較大的,即左右子樹中同值路徑較長的。

class solution 

int result = 0;

private int find(treenode root)

}

二叉樹路徑和問題

今天回顧了一下二叉樹給定sum的問題,邏輯還是有問題,本以為對的,寫了如下的 bool haspathsum treenode root,int sum if path sum return true p s.top s.pop if p left null path p left val p p ...

二叉樹路徑搜尋問題

1 求任意二叉樹中的所有路徑 細想一下,這其實是乙個dfs問題。有乙個helper函式,用來向list中新增string。這裡為什麼要用靜態的string而不是動態的stringbuilder?另乙個問題是,要動態地新增內容給list,從思路上講應該是回溯法。回溯用動態子結構比如list的話,就需要...

演算法 二叉樹路徑問題

二叉樹的路徑問題一般可以用dfs搜尋來解決,遞迴的思想一定要理解 注重最後一步和終止條件 public boolean haspathsum treenode root,int sum sum root.val if sum 0 root.left null root.right null 找一下左...