Combination Sum II medium
Problem Statement
Given a collection of candidate numbers (candidates
) and a target number (target
), find all unique combinations in candidates
where the candidate numbers sum to target
.
Each number in candidates
may only be used once in the combination.
Note: The solution set must not contain duplicate combinations.
Example 1
Input: candidates
= [10,1,2,7,6,1,5], target
= 8
Output:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]
Example 2
Input: candidates
= [2,5,2,1,2], target
= 5
Output:
[
[1,2,2],
[5]
]
Steps
-
Sort the input array: Sorting allows us to easily skip duplicate numbers and avoid generating duplicate combinations.
-
Backtracking: Use a recursive backtracking approach to explore all possible combinations.
-
Recursive function: The recursive function takes the following parameters:
index
: The current index in thecandidates
array.combination
: The current combination being built.remaining
: The remaining sum needed to reach the target.
-
Base cases:
- If
remaining
is 0, a valid combination is found. Add it to the result list. - If
remaining
is negative orindex
is out of bounds, backtrack.
- If
-
Recursive step:
- Include: Recursively call the function with the current number included in the combination (
index + 1
, updatedcombination
, and updatedremaining
). Skip duplicate numbers by checking the next element if it's the same. - Exclude: Recursively call the function without including the current number (
index + 1
, unchangedcombination
, and unchangedremaining
).
- Include: Recursively call the function with the current number included in the combination (
-
Return: Return the list of unique combinations.
Explanation
The backtracking algorithm systematically explores all possible combinations. Sorting the input array ensures that duplicate combinations are not generated. The skipping of duplicate numbers in the "Include" step is crucial for efficiency and correctness. The base cases handle the termination conditions of the recursion.
Code
using System;
using System.Collections.Generic;
using System.Linq;
public class Solution {
public IList<IList<int>> CombinationSum2(int[] candidates, int target) {
IList<IList<int>> result = new List<IList<int>>();
Array.Sort(candidates); //Sort for efficiency and duplicate removal
Backtrack(candidates, target, 0, new List<int>(), result);
return result;
}
private void Backtrack(int[] candidates, int target, int index, List<int> combination, IList<IList<int>> result) {
if (target == 0) {
result.Add(new List<int>(combination)); //Add a copy to avoid modification
return;
}
if (target < 0 || index >= candidates.Length) {
return;
}
// Include
combination.Add(candidates[index]);
Backtrack(candidates, target - candidates[index], index + 1, combination, result);
combination.RemoveAt(combination.Count - 1); //Backtrack: remove the last added element
// Exclude (Skip duplicates)
int skipIndex = index + 1;
while (skipIndex < candidates.Length && candidates[skipIndex] == candidates[index]) {
skipIndex++;
}
Backtrack(candidates, target, skipIndex, combination, result);
}
}
Complexity
- Time Complexity: O(2N * k), where N is the number of candidates and k is the average length of combinations. The worst-case scenario is exploring all possible subsets.
- Space Complexity: O(k * x), where k is the average length of combinations and x is the number of combinations. The space is mainly used for the recursion stack and storing the combinations. In the worst case, it could be O(N * 2N), if all combinations have length N.