二叉樹 路徑搜尋中的一些問題

2021-10-05 16:25:55 字數 4572 閱讀 3293

目錄前言

1、求二叉樹的最大深度 leetcode104

2、求二叉樹的最小深度 leetcode111

3、求二叉樹的正向/逆向數字路徑和 leetcode129

4、求二叉樹的節點路徑和 leetcode437

5、小結(重要)

二叉樹的路徑搜尋就是乙個簡易版的行程回溯演算法,之所以是簡易版是因為行程路徑最多僅有兩條。因此,如果只要搜尋一條滿足條件的路徑,搜尋到即可停止,參見 leetcode 112. 路徑總和。如果需要搜尋多條滿足條件的路徑,搜尋本節點時需要修改行程,搜尋完畢後需要恢復原來的行程,參見 leetcode 113.

路徑總和 ii 。

public static int countmaxdeepth(treenode root)

return math.max(countmaxdeepth(root.left),countmaxdeepth(root.right)) + 1;

}

dfs、bfs都行。

本題的核心在於:二叉樹的最小深度含義是距離根節點最近的葉節點層數

1、葉子節點的定義是左孩子和右孩子都為 null 時叫做葉子節點

2、當 root 節點左右孩子都為空時,返回 1

3、當 root 節點左右孩子有乙個為空時,返回不為空的孩子節點的深度,而不是本節點 + 1 //最易出錯的點

4、當 root 節點左右孩子都不為空時,返回左右孩子較小深度的節點值

記住以下這個簡單的例子,保證第 3 條不會出錯:

1\2

\3

遞迴**實現如下:

public static int countmindepth(treenode root)

int min = 0;

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

return min + 1;

}

上面的**的時間複雜度恒為o(n),也就是說需要遍歷樹中的所有節點,假設我們找到了乙個距離根節點的葉節點,更新當前的葉節點的層數 mindepth,後面當搜尋的層數 depths 大於 mindepth 時停止搜尋。

**實現:

public static int countmindepth(treenode root)		

countmindepth(root,1);

return mindepth; }

private void mindepth = integer.max_value;

public void countmindepth(treenode root,int depth)

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

countmindepth(root.left,depth+1);

countmindepth(root.right,depth+1);

}

也可以使用bfs法,搜尋到葉節點就停止。平衡二叉樹是本演算法的最壞情況。

public int sumnumbers(treenode root) 

//正序根節點是高位,葉節點是低位

public int sumnumbers(treenode root,int cursum)

int sum = cursum*10 + root.val;

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

return sumnumbers(root.left,sum) + sumnumbers(root.right,sum); }

//逆序根節點是低位,葉節點是高位

public int sumnumbers(treenode root,int cursum,int decimal)

int sum = cursum + decimal*root.val;

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

return sumnumbers(root.left,sum,decimal*10) + sumnumbers(root.right,sum,decimal*10);

}

逆序求和:葉節點是高位,根節點是低位,需要將樹的層數即數字的位數 傳遞到底層直至葉節點。

參見 leetcode 437. 路徑總和 iii,面試題 04.12. 求和路徑 。給定一棵二叉樹,其中每個節點都含有乙個整數數值(該值或正或負)。設計乙個演算法,列印節點數值總和等於某個給定值的所有路徑的數量。注意,路徑不一定非得從二叉樹的根節點或葉節點開始或結束,但是其方向必須向下(只能從父節點指向子節點方向)。示例:給定如下二叉樹,以及目標和sum = 22。

5

/ \4 8

/ / \

11 13 4

/ \ / \

7 2 5 1

返回:3

解釋:和為 22 的路徑有:[5,4,11,2], [5,8,4,5], [4,11,7]

方法一:暴力破解

儲存 當前節點值 給下一層使用,第 n 層節點都知道(1,2,.. n-1)層節點到本層節點的路徑之和。複雜度o( n * levels)。

public int pathsum(treenode root, int sum) 

private int hasviladpathcnt = 0;

public void pathsum(treenode root, listsumlist,int targetsum)

int listsize = sumlist.size();

for(int i = 0; i < listsize; i++)

sumlist.set(i,tmp);//更新目標和序列

}if(targetsum == root.val)

sumlist.add(targetsum - root.val); //本節點新增到目標和路徑中

pathsum(root.left, sumlist,targetsum);

pathsum(root.right, sumlist,targetsum);

sumlist.remove(listsize);//刪除本節點

for(int i = 0; i < listsize; i++)

}

方法二:暴力破解2,深度搜尋

對樹中的每個節點進行 dfs 路徑匹配,類似於leetcode1367. 二叉樹中的列表,具體說:以樹中的任一節點為起點向下搜尋所有路徑,查詢滿足條件的路徑。

public int dfspathsum(treenode root, int sum) 

sum = sum - root.val;

int len = 0;

if(sum == 0)

return len + dfspathsum(root.left,sum) + dfspathsum(root.right,sum);

} public int pathsum(treenode root, int sum)

//本節點為起點進行深搜,本節點的左右子樹繼續深搜

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

}

1、路徑滿足條件即給定的目標和 targetsum 通常可以用逐次的減去當前節點的值 val,當減到0時即滿足路徑和的條件。這樣可以減少乙個引數 cursum(當前路徑之和)。

2、遞迴搜尋的過程中需要,注意空間節點 (root ==  null) 的處理,當該節點為空的返回值是什麼? false、true、0、等異常值需要重點考慮。

3、普通節點處理需要分為四種邏輯:

1)左、右子節點為空(葉節點),(root.left == null && root.right == null);

2)左子節點為空右子節點不為空(無左子樹),(root.left == null && root.right != null);

3)右子節點為空左子節點不為空(無右子樹),(root.left!= null && root.right == null);

4)左、右子節點不為空(普通節點),(root.left != null && root.right != null);

二叉樹的一些問題

二叉樹的先序遍歷 遞迴 void preorder btnode ptr 二叉樹中序遍歷 遞迴 void inorder btnode ptr 二叉樹後序遍歷 遞迴 void pastorder btnode ptr 先序遍歷二叉樹 非遞迴 void nicepastorder btnode ptr...

關於二叉樹的一些問題

tips 關於二叉樹的絕大多數問題都可以用遞迴方法來實現,dfs。一位二叉樹根節點去掉之後又分為兩個子樹,對於子樹本身也可以看左二叉樹來處理。所以遞迴可以說很好用了 二叉樹的建立 public class bittree public bittree int data public static b...

二叉樹路徑搜尋問題

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