程式呼叫自身的程式設計技巧稱為遞迴。
舉例說明一下:
public void recursion(int n)
}
當n=2的時候首先執行recursion(2),接著執行recursion(1),最後結果就是1和2。
遞迴的呼叫實質就像是乙個堆疊,當我們執行recursion(2)的時候發現無法得到結果並且接著執行recursion(1),此時就相當於把recursion(2)存入棧中,然後執行完recursion(1)的再從棧中取出recursion(2)執行得到結果。
如果是for迴圈加上遞迴呢
public void recursion(int n)}}
對於這種問題,我個人認為乙個很好的辦法就是去分層理解。
recursion(2)-> 輸出次數:3^1
呼叫3次recursion(1)
輸出三次2
每一次的recursion(1)-> 輸出次數:3^2
呼叫3次recursion(0)
輸出三次1
給定兩個整數 n 和 k,返回 1 … n 中所有可能的 k 個數的組合。
示例
輸入: n = 4, k = 2
輸出:[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]分析:
首先可以看出是乙個組合問題
對於例題來看
1.如果組合裡有 1 ,那麼需要在 [2, 3, 4] 裡再找 1 個數;
2.如果組合裡有 2 ,那麼需要在 [3, 4] 裡再找 1數。注意:這裡不能再考慮 1,因為包含 1 的組合,在第 1 種情況中已經包含。
所以這裡使用回溯演算法,首先畫出遞迴樹
然後通過遞迴操作繼續取數,只需注意在取下乙個數時要捨去不需要的數
public class solution
// 我們取數是從1開始取
dequepath = new arraydeque<>();
dfs(n, k, 1, path, res);
return res;
}private void dfs(int n, int k, int begin, dequepath, list> res)
// 從1開始取數
for (int i = begin; i <= n; i++) }}
初步完成後發現**可以進行優化(剪枝操作)
例如這個立體中當我們取的第乙個數為4的時候以及沒有意義了,因為第二個數無論取什麼都已經重複了。
繼續分析:如果n=8,k=5時,從5開始搜尋就沒有意義了,因為把5選上後面6,7,8也組不成5個數了。
所以:
當path.size()==1時,還需要選4個數,最大搜尋起點為5
當path.size()==2時,還需要選3個數,最大搜尋起點為6
當path.size()==3時,還需要選2個數,最大搜尋起點為7
當path.size()==4時,還需要選1個數,最大搜尋起點為8
根據上面可以看出n = 還需要選擇的個數 + 最大搜尋起點 + 1
所以我們可以把迴圈的上界限制為n - 還需選擇的個數 + 1
即 for迴圈修改為i < n - (k - path.size()) + 1;
for (int i = begin; i <= n - (k - path.size()) + 1; i++)
數獨遊戲(sudoku)演算法 回溯 剪枝
具體數獨遊戲是什麼,我就不介紹了,好像多餘了,你能來看這篇文章,說明你對數獨遊戲已經有了相當的了解了!還是入正題吧,今天先講解和發下用回溯 剪枝 求數獨遊戲,我也看了些回溯 剪枝求數獨的演算法,很惱火,既沒注釋,而且演算法沒有通用性。今天我給大家講的回溯 剪枝法,不僅可以用於解決數獨問題,而且還可以...
演算法訓練 剪格仔(dfs 剪枝 回溯)
題目描述 如下圖所示,3 x 3 的格仔中填寫了一些整數。10 1 52 20 30 1 1 2 3 我們沿著圖中的星號線剪開,得到兩個部分,每個部分的數字和都是 60。本題的要求就是請你程式設計判定 對給定的 m x n 的格仔中的整數,是否可以分割為兩個部分,使得這兩個區域的數字和相等。如果存在...
DFS 回溯與剪枝 C N皇后問題
c n皇后問題 在n n的方格棋盤放置了n個皇后,使得它們不相互攻擊 即任意2個皇后不允許處在同一排,同一列,也不允許處在與棋盤邊框成45角的斜線上。你的任務是,對於給定的n,求出有多少種合法的放置方法。input共有若干行,每行乙個正整數n 10,表示棋盤和皇后的數量 如果n 0,表示結束。out...