具体题目:
解题:


这样解题出来是无法运行的,问题是少了这个
递归回溯函数backtrack
返回值:int**,二维数组,所有答案组合。
*returnSize:输出参数,告诉调用者一共多少组答案。
*returnColumnSizes:输出参数,int 数组,每个元素记录对应组合有几个数字。
正确的解题:


运行结果:
一、读题
1、每个数字在一个组合里只能用 1 次(数组本身可以有重复元素,比如数组有两个 1,结果可以
用两个 1,但不能同一个位置元素重复选)
2、最终结果不能有重复组合,比如不能同时出现1,7和7,1,也不能两个一模一样的1,1,6
3、找出所有和等于 target 的组合。
和之前对比【组合总和 I】:I 里面元素可以无限复用;II 每个元素最多选一次,数组存在重复数字。
重点: 解决去重:
1、先排序数组!把相同数字挨在一起。排序是去重的前提。
2、回溯 dfs:传参:当前遍历起始下标 start,当前路径 path,剩余需要凑的数remain。
start:保证不从前面回头选,避免1,7和7,1这种顺序不同的重复。
因为元素只能选一次:递归下一层 start = i+1,而不是 i(组合 I 是 start=i,可以重复选自己)
3、同层去重:如果 for 循环当前 i>start,并且candidatesi==candidatesi‑1,直接 continue 跳过。
区分:
i>start:代表同一层递归,遇到和前一个一样的值,跳过,防止产生重复组合;
如果 i==start,是深度往下走,允许选重复数字(比如两个 1 的情况,允许取两个 1)。
4、剪枝
排序后,如果candidatesi>remain,后面更大,直接 break。
三、
1、qsort排序:10,1,2,7,6,1,5排序后变成1,1,2,5,6,7,10。相同数字相邻。
2、backtrack中i>start && candidatesi==candidatesi‑1 continue;
i==start:代表深度往下搜,可以取第二个 1;
i>start:同一层循环,前面已经用过这个数字产生过答案,跳过,防止重复组合。
3、递归调用参数i+1:和组合总和 I 最大区别! 每个元素只能选一次,下一轮不能再访问 i 下标。组合 I 传 i,可以重复选取。
4、candidatesi>remain break:排序后剪枝,后面数字更大,没必要继续循环。
四、终止
remain==0,剩余需要凑的数等于0,当前path就是有效组合。
要把path复制一份存进res(不能直接存进path数组,因为path后续回溯会被覆盖修改)