组合总和 II

组合总和 II

CategoryDifficultyLikesDislikes
algorithmsMedium (62.12%)737-

Tags

array | backtracking

Companies

snapchat

给定一个数组  candidates  和一个目标数  target ,找出  candidates  中所有可以使数字和为  target  的组合。

candidates  中的每个数字在每个组合中只能使用一次。

注意: 解集不能包含重复的组合。

示例  1:

1
2
3
4
5
6
7
8
输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]

示例  2:

1
2
3
4
5
6
输入: candidates = [2,5,2,1,2], target = 5,
输出:
[
[1,2,2],
[5]
]

提示:

  • 1 <= candidates.length <= 100
  • 1 <= candidates[i] <= 50
  • 1 <= target <= 30

Discussion | Solution

解法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
struct Solution;

// @lc code=start
impl Solution {
    /// ## 解题思路
    /// - 回溯
    /// 本题在39.组合总和基础上,增加两个改进即可
    pub fn combination_sum2(candidates: Vec<i32>, target: i32) -> Vec<Vec<i32>> {
        ///
        fn combine_sum(candidates: &[i32], left: i32, sub: &[i32], res: &mut Vec<Vec<i32>>) {
            match left {
                n if n < 0 => return,
                0 => {
                    res.push(sub.to_vec());
                    return;
                }
                _ => {
                    candidates
                        .iter()
                        .filter(|&c| *c <= left)
                        .enumerate()
                        .filter(|(i, &c)| (*i < 1 as usize) || c != candidates[i - 1])
                        .for_each(|(i, c)| {
                            let mut s = sub.to_vec();
                            s.push(*c);
                            combine_sum(&candidates[i + 1..], left - c, &s, res);
                        });
                }
            }
        }

        let mut res: Vec<Vec<i32>> = vec![];
        let mut c = candidates.to_vec();
        c.sort();
        combine_sum(&c, target, &vec![], &mut res);
        res
    }
}
// @lc code=end

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Solution {
    vector<vector<int>> result;
public:
    /**
    * ## 解题思路
    * * 回溯法,在第39的基础上,改变递归时的判断条件
    */
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {

        vector<int> tmp;
        sort(candidates.begin(), candidates.end());
        dfs(candidates, tmp, target, 0);
        return result;
    }

    void dfs(vector<int>& candidates, vector<int>& tmp, int target, int s) {
        if (target < 0) {
            return;
        }
        if (target==0) {
            result.push_back(tmp);
        }
        for (int i=s; i<candidates.size(); i++) {
            // 当前元素大于剩余target, 或
            // 当前相等元素已经去过,则跳过
            if (candidates[i]>target || (i>s && candidates[i] == candidates[i-1])) {
                continue;
            }
            //
            tmp.push_back(candidates[i]);
            //当前元素只取一次,下次取后一个
            dfs(candidates, tmp, target-candidates[i], i+1);
            tmp.pop_back();
        }
    }
};
updatedupdated2024-08-252024-08-25