使用遞歸的時候應該注意不可使用后加,就是n++或者n--
因為在遞歸中使用n++作為最終跳出遞歸的語句時候回導致遞歸陷入死循環
因為首先程序自己調用自己的時候,先去執行自己調用自己的程序,一直處在自己調用自己的狀態,導致在第一次調用自己的 時候就不能完成,所以后加或者后減操作是隨着遞歸操作從后向前操作的。
下面的遞歸調用不使用乘除法或者循環的情況下實現0到n的累加
public class Solution { public int Sum_Solution(int n) {if(n==0) return 0; return n+=Sum_Solution(--n); } }
上面就是很好的例子,將sum_solution()中修改成n--程序就會出現問題。
下面順便梳理一下遞歸調用怎樣實現數據累加或者累乘:
而本次的返回結果需要包括上一次的返回結果,並且加上當前的返回結果。核心就是每次需要加上當前的控制遞歸的變量,遞歸變量只能和一個變量相關。(不知道使用集合類行不行)
遞歸的控制變量有時候需要
下面是一段實現查找二叉樹中,找到第k小的數
class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } public class Solution { int i=0; TreeNode KthNode(TreeNode pRoot, int k) { if(pRoot!=null){ TreeNode result=null; result=KthNode(pRoot.left,k); if(result!=null){ return result; //如果result不是null的,說明result中存在我們想向上拋出的結果,不需要向下進行的必要了(已經找到了),繼續向上拋出 } i++; if(k==i){ return pRoot; //確定向上拋出的是誰 } result=KthNode(pRoot.right,k); if(result!=null){ return result; } } return null; } }
在這里需要考慮的一個就是如何實現最終結果的層層拋出,並且在找到之后停止遞歸查找
首先明確的是向上拋出的一定是TreeNode類型的,就是要在查找到第k個數的時候向上拋出在這個位置的TreeNode,
但是向上拋出的同時,需要有上層接受並且繼續向上拋出(其實這個向上拋出的動作就有中斷遞歸的效果),
總結上面就是返回的結果一定和遞歸的函數有着直接或者間接的聯系
下面這段代碼實現的是刪除有序鏈表中的重復的,所有重復的都要刪除一個不剩,突然發現可以實現有條件的遞歸,
public ListNode deleteDuplication(ListNode pHead) { ListNode p; if(pHead==null || pHead.next==null) { //如果第一個或者第二個是null,不需要執行遞歸直接返回 return pHead; } if(pHead.val==pHead.next.val) //這個分支用於跳過鏈表中重復的部分,注意使用變量p,可以減少使用.next訪問,增加代碼的速度。 { p=pHead.next; while(p!=null && p.val==pHead.val) { p = p.next; } return deleteDuplication(p); } else //因為前面的重復節點都被刪除,,所以如果這個節點和后面的節點不重復,他就是不重復的,需要保留,那就直接遞歸下一個節點 { pHead.next=deleteDuplication(pHead.next); //這里還要注意一點返回的處理,這里使用的從前到后的思想 return pHead; } }
遞歸的三大步驟:
(1)確定函數的功能
(2)確定函數的終止條件
(3)由函數之間的遞歸關系確定函數的返回形式(最難的一步)(還要注意遞歸中出現的重復問題,就像在斐波那契數列中的那樣,使用數組實現,減少遞歸的重復的問題)
就上面的這個說說:其從前往后的形式,前面處理過,就調用它后面部分,一層一層的遞歸循環下去。直到達到結束條件返回
