首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

LeetCode 39. Combination Sum:回溯算法詳解與 C++ 實現

     編輯:關於C++

題目描述

給定無重複元素的正整數數組 candidates 和目標值 target,找出所有組合使元素和等于 target。candidates 中的數字可無限次重複選取。解集不能包含重複組合,組合內元素非遞減序。

示例:candidates = [2,3,6,7], target = 7 → [[7], [2,2,3]]。

解題思路:回溯 + 剪枝

  1. 先對 candidates 排序,便於剪枝與保證非遞減序。
  2. 遞歸函數 backtrack(start, path, remain):
    • start:當前搜索起始索引,避免排列重複(只考慮當前及之後的元素)。
    • path:當前組合。
    • remain:剩餘目標值。
  3. 若 remain == 0,將 path 加入結果集。
  4. 從 start 遍歷到末尾:
    • 若 candidates[i] > remain,剪枝(後續更大)。
    • 將 candidates[i] 加入 path,遞歸調用 backtrack(i, path, remain - candidates[i])(注意傳 i 而非 i+1,允許重複使用)。
    • 回溯:彈出 path 最後元素。

C++ 代碼實現

class Solution {
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        sort(candidates.begin(), candidates.end());
        vector<vector<int>> result;
        vector<int> path;
        backtrack(candidates, target, 0, path, result);
        return result;
    }

private:
    void backtrack(const vector<int>& candidates, int remain, int start,
                   vector<int>& path, vector<vector<int>>& result) {
        if (remain == 0) {
            result.push_back(path);
            return;
        }
        for (int i = start; i < candidates.size(); ++i) {
            if (candidates[i] > remain) break; // 剪枝
            path.push_back(candidates[i]);
            backtrack(candidates, remain - candidates[i], i, path, result);
            path.pop_back();
        }
    }
};

複雜度分析

  • 時間:指數級,最壞情況取決於目標值與最小元素的比值。實際上受剪枝影響較小。
  • 空間:O(target / min_val) 遞歸棧深度 + 存儲結果空間。

關鍵點總結

  1. 排序是剪枝與去重的前提。
  2. 傳遞 i 而非 i+1 實現元素可重複使用。
  3. 傳遞引用 path 並手動 push/pop 避免拷貝開銷。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved