代碼隨想錄算法訓練營|第二十七天|回溯算法理论基础、77. 组合。刷题心得(c++)

本文介绍了回溯算法的基本概念,重点讨论了组合问题的解决方法,包括未剪枝和剪枝策略,并分享了作者在实践中的理解和经验,包括遇到的困难和学习收获。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

讀題

回溯算法理论基础

77. 组合

看完代码随想录之后的想法

77. 組合 - 實作

思路

未剪枝(未縮小遍歷範圍)

剪枝(縮小遍歷範圍)

代碼

未剪枝(未縮小遍歷範圍)

剪枝(縮小遍歷範圍)

總結

自己实现过程中遇到哪些困难

今日收获,记录一下自己的学习时长

相關資料

第七章 回溯算法part01

理论基础

77. 组合


讀題

回溯算法理论基础

看完回溯算法理論基礎後,主要有幾個重點

  1. 效能: 回溯算法本質是窮舉法,就算可以縮小範圍,但本質並非是個高效的算法

  2. 能解決的問題

    • 組合: N個數裡面根據一定規則找出K個數的集合
    • 排序: N個數裡面根據一定規則排序,有多少排列方式
    • 切割: 字符串按一定規則有幾種切割方式
    • 子集: 一個N個數的集合有多少符合條件的子集
    • 棋盤: N皇后、解數獨
  3. 回溯法模板

    void backtracking(參數) {
    		if (終止條件) {
    				存放結果;
    				return;
    		}
    		
    		for(選擇: 本層有多少元素){
    				處理節點;
    				backtracking(路徑,選擇列表) \\\\遞迴
    				回溯,撤銷處理結果
    		}
    		return;
    }
    
  4. 模板中的for迴圈可以理解為橫向遍歷、遞迴可以理解為縱向遍歷,如下圖(圖來源: 代碼隨想錄)

77. 组合

看完代码随想录之后的想法

看完之後,可能因為有先做二叉樹的題目,所以理解不難,今天在看完解題之後,過了兩三個小時回到電腦前認真做題,因為對於觀念很清晰,所以一般解法以及剪枝的寫法都不難理解

77. 組合 - 實作

思路

未剪枝(未縮小遍歷範圍)

  1. 建立results儲存結果,建立path建立符合條件的結果
  2. 建立函數backtracking
    1. 參數n , k , startindex (startindex 決定下一層由那裡開始)
    2. 終止條件: 如path的長度 == k 代表已找到組合,將結果放入results 並return
    3. 單遞迴
      1. for 橫向遍歷
      2. 處理當前數值放入path
      3. backtracking 遞迴,縱向遍歷
      4. 回溯操作,撤回之前放入的值
  3. 主函數
    1. 遞迴
    2. return results

剪枝(縮小遍歷範圍)

  1. 建立results儲存結果,建立path建立符合條件的結果
  2. 建立函數backtracking
    1. 參數n , k , startindex (startindex 決定下一層由那裡開始)
    2. 終止條件: 如path的長度 == k 代表已找到組合,將結果放入results 並return
    3. 單遞迴
      1. for 橫向遍歷,並且由最多遍歷到長度n,改為"最多”遍歷到n - (k - path.size()) + 1 的長度,+1是因為要包含自己。
      2. 處理當前數值放入path
      3. backtracking 遞迴,縱向遍歷
      4. 回溯操作,撤回之前放入的值
  3. 主函數
    1. 遞迴
    2. return results

代碼

未剪枝(未縮小遍歷範圍)

class Solution {
public:
    vector<vector<int>> results;
    vector<int> path;
    void backtracking(int n, int k, int startindex) {
        //終止條件
        if( path.size() == k) {
            results.push_back(path);
            return;
        }
        //單遞迴
        for(int i = startindex; i <= n ; i++){
            path.push_back(i);
            backtracking(n, k, i + 1); //i + 1 是因為要遞迴i後面的值
            path.pop_back(); //回溯操作
        }
    }
    vector<vector<int>> combine(int n, int k) {
        backtracking(n, k, 1); //數由1開始,所以要帶入1
        return results;
    }
};

剪枝(縮小遍歷範圍)

class Solution {
public:
    vector<vector<int>> results;
    vector<int> path;
    void backtracking(int n, int k, int startindex) {
        //終止條件
        if( path.size() == k) {
            results.push_back(path);
            return;
        }
        //單遞迴,n - 目標長度與目前長度的差
        for(int i = startindex; i <= n - (k - path.size()) + 1 ; i++){
            path.push_back(i);
            backtracking(n, k, i + 1); //i + 1 是因為要遞迴i後面的值
            path.pop_back(); //回溯操作
        }
    }
    vector<vector<int>> combine(int n, int k) {
        backtracking(n, k, 1); //數由1開始,所以要帶入1
        return results;
    }
};

 

總結

自己实现过程中遇到哪些困难

今天因為有先聽卡哥講解,所以在理解上沒有遇到太大的困難,只是需要多練習這些題目

今日收获,记录一下自己的学习时长

今天大概學習1.5hr ,整體對於回溯的作法有了新的認知。

相關資料

● 今日学习的文章链接和视频链接

第七章 回溯算法part01

理论基础

题目链接/文章讲解:https://programmercarl.com/回溯算法理论基础.html

视频讲解:带你学透回溯算法(理论篇)| 回溯法精讲!_哔哩哔哩_bilibili

77. 组合

题目链接/文章讲解:https://programmercarl.com/0077.组合.html

视频讲解:带你学透回溯算法-组合问题(对应力扣题目:77.组合)| 回溯法精讲!_哔哩哔哩_bilibili

剪枝操作:带你学透回溯算法-组合问题的剪枝操作(对应力扣题目:77.组合)| 回溯法精讲!_哔哩哔哩_bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值