日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

77. 组合(回溯算法)

發布時間:2025/3/21 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 77. 组合(回溯算法) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

給定兩個整數 n 和 k,返回范圍 [1, n] 中所有可能的 k 個數的組合。
你可以按 任何順序 返回答案。

示例 1:
輸入:n = 4, k = 2
輸出:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]

示例 2:
輸入:n = 1, k = 1
輸出:[[1]]

提示:

1 <= n <= 20
1 <= k <= n

這道題是典型的回溯題目,回溯算法雖然效率不怎么高但是在一些情況下只能用回溯去解決,就比如這道題目,如果暴力解法的話是做不出來的,回溯算法一般都是在集合中遞歸找子集,為了更方便去理解,回溯算法解決的問題可以理解為一個N叉樹問題,就以這道題目為例子,我們來看看如何解決;

首先確定回溯函數backtracking到底該怎么寫,
返回值先假設為void,傳入參數k和n肯定是要有的,這里還額外需要一個start來記錄本層遞歸的中,集合從哪里開始遍歷;

怎么理解呢,這道題如果轉化為一個N叉樹的話,那么k就是樹的最大深度,n就是這個樹的寬度,所以我們需要一個循環來遍歷n,即對寬度的遍歷,循環中套遞歸,對每一個寬度進行遞歸,所以遞歸其實實現的是深度的遍歷;

回溯函數其實就是一個遞歸函數,所以終止條件該是什么?
如果一個樹通過dfs的方式遍歷,一旦到了葉子節點就可以結束了,所以這里也一樣,一旦遞歸深度達到了k(即最大深度),就可以結束了;

代碼如下:

class Solution { public:vector<vector<int>> ans;vector<int> path;void backtracking(int n, int k, int start) {if (path.size() == k) {ans.push_back(path);return ;}for (int i = start; i <= n; ++i) {path.push_back(i);backtracking(n, k, i + 1); //遞歸深度,i + 1代表下一層寬度起點要從下一個開始path.pop_back();//回溯來撤銷處理的節點(畫圖就好理解了)}}vector<vector<int>> combine(int n, int k) {backtracking(n, k, 1);return ans;} };

這個代碼同樣可以通過剪枝優化一下,只需要改一下寬度遍歷中的n,
優化需要以下幾步:
已經選擇的元素個數:path.size();
還需要的元素個數為: k - path.size();
在集合n中至多要從該起始位置 : n - (k - path.size()) + 1開始遍歷
這里加1是為了包括了起始位置
最后優化后其實只需要改動對寬度的循環這一欄就可以了,即

for (int i = start; i <= n - (k - path.size()) + 1; ++i)

代碼如下:

class Solution { public:vector<vector<int>> ans;vector<int> path;void backtracking(int n, int k, int start) {if (path.size() == k) {ans.push_back(path);return ;}for (int i = start; i <= n - (k - path.size()) + 1; ++i) {path.push_back(i);backtracking(n, k, i + 1);path.pop_back();}}vector<vector<int>> combine(int n, int k) {backtracking(n, k, 1);return ans;} };

總結

以上是生活随笔為你收集整理的77. 组合(回溯算法)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。