關於遞迴在求解路經和中的應用

2021-10-08 18:32:38 字數 3060 閱讀 4731

覺得遞迴其實就是數學歸納法的逆運算。

第一:明確要遞迴的函式要實現的功能,一定要相信這個函式可以完成任務;

第二:不要去考慮細枝末節和它時如何實現的,只考慮當前。

第三:找好終止條件;

下面我們來做路徑總和的三道題:

112. 路徑總和

這個題目是判斷從根到葉子節點的路徑和是否等於乙個數。首先我們haspathsum(root,sum)這個函式的作用是找出以root為根的樹的路徑和等於sum的個數,我們相信它可以實現。接下來找終止條件如果root是葉子節點的話,那麼只能判斷它是否等於sum,如果不等於返回0,等於返回1。如果不是的話,那麼就判斷左右子樹和sum-root.val.

按照上面做三點來做題,首先明確haspathsum函式可以實現判斷以root為節點的樹有沒有和為sum的功能,如何進行下一步呢,是不是就是以左節點或者右節點為根,sum為sun-root,val呢,然後再去考慮終止條件。

**如下:

class solution 

}

113. 路徑總和 ii

這個題目和上一題不同的是,要返回所有的路徑。首先想到的是使用回溯演算法。

**如下:

class solution 

public void dfs(treenode root,int sum,linkedlistlist)

dfs(root.left,sum-root.val,list);

dfs(root.right,sum-root.val,list);

list.removelast();

}}

437. 路徑總和 iii

這個題目也是統計路徑和等於某個sum的路徑數量並且返回 ,但是和第一題不同的是路徑不需要從根節點開始,也不需要在葉子節點結束,但是路徑的方向是向下的。

這個題目使用雙重遞迴來做。首先第乙個用來遞迴遍歷每乙個節點,第二個用來統計以每個節點為根的所有滿足條件的路徑。**如下

class solution 

//count(root,sum)統計以根為節點的路徑數量;

//pathsum(root.left,sum)以根的左子樹為節點

//尋找以此刻節點為根,路徑和等於sum的路徑數量

public int count(treenode root,int sum)

}

這個題目也可以使用字首和來做。字首和就是從根節點到當前節點的所有節點的和。因為存在節點值為負數的情況,因此可能存在當前字首和等於sum的情況,繼續向下遍歷幾個節點之後,字首和還等於sum的情況。用map記錄《當前的字首和currsum,這個字首和出現的次數》。此時假如我們到了c節點,此時的字首和是currsum,我們計算一下currsum-sum,如果在map裡存在這樣的字首和的話,那麼說明從那個節點到c節點這個路徑就是我們要的路徑。那麼我們將這個字首和的數量加上即可。然後再遞迴進入c節點的左右子樹。

還有**如下:

class solution 

/*** 字首和的遞迴回溯思路

* 從當前節點反推到根節點(反推比較好理解,正向其實也只有一條),有且僅有一條路徑,因為這是一棵樹

* 如果此前有和為currsum-target,而當前的和又為currsum,兩者的差就肯定為target了

* 所以字首和對於當前路徑來說是唯一的,當前記錄的字首和,在回溯結束,回到本層時去除,保證其不影響其他分支的結果

* @param node 樹節點

* @param prefixsumcount 字首和map

* @param target 目標值

* @param currsum 當前路徑和

* @return 滿足題意的解

*/private int recursionpathsum(treenode node, mapprefixsumcount, int target, int currsum)

// 2.本層要做的事情

int res = 0;

// 當前路徑上的和

currsum += node.val;

//---核心**

// 看看root到當前節點這條路上是否存在節點字首和加target為currsum的路徑

// 當前節點->root節點反推,有且僅有一條路徑,如果此前有和為currsum-target,而當前的和又為currsum,兩者的差就肯定為target了

// currsum-target相當於找路徑的起點,起點的sum+target=currsum,當前點到起點的距離就是target

res += prefixsumcount.getordefault(currsum - target, 0);

// 更新路徑上當前節點字首和的個數

prefixsumcount.put(currsum, prefixsumcount.getordefault(currsum, 0) + 1);

//---核心**

// 3.進入下一層

res += recursionpathsum(node.left, prefixsumcount, target, currsum);

res += recursionpathsum(node.right, prefixsumcount, target, currsum);

// 4.回到本層,恢復狀態,去除當前節點的字首和數量

prefixsumcount.put(currsum, prefixsumcount.get(currsum) - 1);

return res;

}}

124. 二叉樹中的最大路徑和

這個題目不好理解,很容易繞進去。

因為要遍歷二叉樹所以還是要用遞迴。

針對某個節點,只有三種選擇:

它自己作為根,那麼它的左右子節點都可以要;

要麼向上返回它加上左節點,要麼向上返回它加上右節點。

因為如果把節點和它的左右節點都返回的話,那麼就會會出現路徑交叉了。

class solution 

public int getmax(treenode root)

}

遞迴在MSSQL開發中的應用

在人力資源管理系統中,常常會有通過工號查詢其所在部門主管的需求,但員工所在部門不一定有主管,可能要在上級才有,這時就需要用遞迴的方式將其主管找出來,mssql create function dbo fn getdepmanager depcode varchar 30 returns varcha...

遞迴在遍歷檔案Tree中的應用

此程式用於結構化輸出檔案各個層級,以及計算檔案整個的大小 計算檔案長度 輸出檔案樹 public class ciotext class filetree public filetree public long getlen public void setlen long len public vo...

關於遞迴的簡單應用

說到遞迴,不得不說乙個經典的公式 f 1 1,f 2 1,f n f n 1 f n 2 n 3,n n 也就是斐波那契數列 fibonacci sequence 又稱 分割數列。轉換成 來表示 public static int f int i else if i 2 else 這裡介紹兩種我在實...