technology-note/算法/leetcode/常规题/Q40.组合总和 2.md
2022-03-10 17:23:59 +08:00

69 lines
2.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
id: "202203102"
date: "2022/03/10 21:15"
title: "Q40 组合总和2(combination-sumⅡ)"
tags: ["java", "leetcode", "dfs"]
index_img: https://qiniupic.fleyx.com/blog/202203101631050.jpg?imageView2/2/w/200
banner_img: https://qiniupic.fleyx.com/blog/202203101631050.jpg
categories:
- "算法"
- "leetcode刷题"
---
<span id="blogIdSpan" style="display:none">202203102</span>
## 解析思路
leetcode 中等难度,题目描述[点击这里](https://leetcode-cn.com/problems/combination-sum-ii/)。
本题属于[组合排序](https://blog.fleyx.com/blog/detail/202203101/)的进阶题型。建议先看[上一篇](https://blog.fleyx.com/blog/detail/202203101/)的解析。
本题跟上一题区别只有一点是**选择的数字不能重复**,如何实现不重复呢?
很简单,只需要将传入的 index 设置成 index+1同时 for 循环时每次都循环到下一个不同的元素上
这样就不会选取到已经选过的元素。
代码如下:
## 代码
```java
public class Q40 {
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(candidates);
dfs(candidates, target, 0, new Stack<>(), res);
return res;
}
private void dfs(int[] candidates, int target, int index, Stack<Integer> temp, List<List<Integer>> res) {
if (target == 0) {
//说明找到一个结果序列
res.add(new ArrayList<>(temp));
return;
}
for (int i = index; i < candidates.length; ) {
if (candidates[i] > target) {
//前面已经排序过所以在这里可以进行剪枝操作如果candidates[index]都小于target了那就不需要比较后面的了肯定不满足要求
return;
}
temp.push(candidates[i]);
dfs(candidates, target - candidates[i], i + 1, temp, res);
temp.pop();
//手动控制i的增长对于同一个数字不能重复处理
int nextI = i + 1;
while (nextI < candidates.length && candidates[nextI] == candidates[i]) {
nextI++;
}
i = nextI;
}
}
public static void main(String[] args) {
new Q40().combinationSum2(new int[]{10, 1, 2, 7, 6, 1, 5}, 8).forEach(System.out::println);
}
}
```