算法记录
LeetCode 题目:
给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
说明
一、题目
candidates 中的每个数字在每个组合中只能使用 一次 。
注意: 解集不能包含重复的组合。
二、分析
- 分析题意可知就是一个全排列的问题,但是针对于边界的处理需要注意分析。
- 从前往后进行贪心排列,但是一旦相同位置出现相同的数据这种情况肯定是已经记录过的,所以此种情况需要进行筛出。
- 上面的边界判断不能解决下一个位置重复的情况,也就是不在当前的整个贪心过程中,这样有可能就会出现数据完全相同的情况,这种边界的处理就是直接进行记录即可,因为是完全相同的数据,因此很好进行判断。
- 注意数组的前期排序解决相邻数据重复问题。
class Solution {
private List<List<Integer>> ret = new ArrayList();
private Set<Integer> map = new HashSet();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
List<Integer> temp = new ArrayList();
Arrays.sort(candidates);
dfs(candidates, target, 0, temp);
return ret;
}
private void dfs(int[] candidates, int target, int start, List<Integer> temp) {
if(target == 0) {
if(map.contains(get(temp))) return;
map.add(get(temp));
ret.add(new ArrayList(temp));
return;
}
for(int i = start; i < candidates.length; i++) {
if(candidates[i] > target) continue;
if(start != i && candidates[i] == candidates[start]) continue;
temp.add(candidates[i]);
dfs(candidates, target - candidates[i], i + 1, temp);
temp.remove(temp.size() - 1);
}
}
public int get(List<Integer> temp) {
int ret = 0;
for(int i : temp) ret = ret * 10 + i;
return ret;
}
}
总结
硬编码能力,注意边界的判断。