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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

leetcode 77. 组合 思考分析

發布時間:2023/12/1 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 leetcode 77. 组合 思考分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

    • 1、題目
    • 2、回溯法思路
    • 3、參考其他思路,更深入了解這個問題
    • 4、剪枝優化

可能需要回顧到的知識文章:
1、常用算法總結(窮舉法、貪心算法、遞歸與分治算法、回溯算法、數值概率算法)
2、回溯法初步
刪除vector容器中的對象元素的三種方法:pop_back, erase與remove算法

1、題目

給定兩個整數 n 和 k,返回 1 … n 中所有可能的 k 個數的組合。

2、回溯法思路

集合元素個數為n,由此可以看出解空間樹每個結點有n孩子,深度為k。
利用模板,就就就AC了。。。
每次確定一個起點和一個終點,從start遍歷到end(對于本層元素而言)。
將第i個元素放入res中,然后進入下一層,下一層的起點是i+1(這樣start只會一直向大的數值延伸,不會產生重復的元素)。
如果不符合就把這個元素pop掉。

class Solution { public:vector<vector<int>> result;vector<int> res;void backtracking(int start,int end,int k){//找到了k個數if(res.size() == k){result.push_back(res);return;}for(int i=start;i<=end;i++){//處理結點;res.push_back(i);//遞歸,探索下一層backtracking(i+1,end,k); //遞歸//回溯,撤銷處理結果res.pop_back();}}vector<vector<int>> combine(int n, int k) {result.clear();res.clear();backtracking(1,n,k);return result;} };

3、參考其他思路,更深入了解這個問題

對于較小的k,我們可以很容易想到for循環嵌套k層解決,如下:
n=4,k=2;

int n = 4; for (int i = 1; i <= n; i++) {for (int j = i + 1; j <= n; j++) {cout << i << " " << j << endl;} }

但是對于較大的k,我們的顯然不能寫嵌套for。例如要解決n=100.k=50的情況,暴力寫法需要嵌套50層for循環,而回溯法就是利用遞歸來解決嵌套層數的問題。
每一層遞歸中嵌套一個for循環,那么遞歸就可以用于解決多層嵌套循環的問題了。
觀察我們的解空間樹:

每次從集合中選取元素,可選擇的范圍隨著選擇的進行而收縮,調整可選擇的范圍。
n相當于樹的寬度,k相當于樹的深度。

4、剪枝優化

下面的遍歷范圍是可以剪枝優化的:

for(int i=start;i<=end;i++) {//處理結點;res.push_back(i);//遞歸,探索下一層backtracking(i+1,end,k); //遞歸//回溯,撤銷處理結果res.pop_back(); }

舉例n=4,k=4時,那么第一層for循環的時候,從元素2開始的遍歷就已經沒有意義了,因為遍歷了也湊不到4個元素了。
所以我們可以剪枝的地方就是每一層的end。
我們已經選擇的元素個數為:res.size()
我們還需要的元素的個數為k-res.size()
所以最多從end-(k-res.size())+1的地方開始遍歷。
所以可以修改為:

for(int i=start;i<=end-(k-res.size())+1;i++) {//處理結點;res.push_back(i);//遞歸,探索下一層backtracking(i+1,end,k); //遞歸//回溯,撤銷處理結果res.pop_back(); }

完整代碼:

class Solution { public:vector<vector<int>> result;vector<int> res;void backtracking(int start,int end,int k){//找到了k個數if(res.size() == k){result.push_back(res);return;}for(int i=start;i<=end-(k-res.size())+1;i++){//處理結點;res.push_back(i);//遞歸,探索下一層backtracking(i+1,end,k); //遞歸//回溯,撤銷處理結果res.pop_back();}}vector<vector<int>> combine(int n, int k) {result.clear();res.clear();backtracking(1,n,k);return result;} };

可以看到速度是有明顯的提升的:

總結

以上是生活随笔為你收集整理的leetcode 77. 组合 思考分析的全部內容,希望文章能夠幫你解決所遇到的問題。

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