Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
Each number in C may only be used once in the combination.
Note:
- All numbers (including target) will be positive integers.
- Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak).
- The solution set must not contain duplicate combinations.
For example, given candidate set 10,1,2,7,6,1,5
and target 8
,
A solution set is: [1, 7]
[1, 2, 5]
[2, 6]
[1, 1, 6]
题目解析:
这道题目和上题基本一样,也是深度优先算法,但是由于不能重复,所以递归还是传递的是i+1!但是由于数据中有重复,只改这一点代码还是有问题,还是会出现重复的数据。那么如何才能避免呢?我们看看递归的情况,当arr[i]<sum的时候,第i个元素入栈。如果第i个元素退出后,如果i+1和i的数据相等,直接令i+1入栈的话,肯定会造成重复。那么我们就进行一点小处理,去掉那些和arr[i]一样的数据,再入栈。代码如下:
如果题目没要求输出的元素按照从小到大,那么也要进行排序,这样才能用上面的方法去掉重复数据!!切记!有时排序不只在时间复杂度上有简化,再其他方面也有!
#include <stdio.h>
#include <stdlib.h>
struct Stk{
int arr[20];
int len;
};
int partition(int arr[],int lo,int hi)
{
int key = arr[lo];
while(lo < hi){
while(lo < hi && arr[hi] >= key)
hi--;
if(lo<hi){
arr[lo] = arr[hi];
}
while(lo < hi && arr[lo] <= key)
lo++;
if(lo<hi)
arr[hi] = arr[lo];
}
arr[lo] = key;
return lo;
}
void QuickSort(int arr[],int lo,int hi)
{
if(lo < hi){
int mid = partition(arr,lo,hi);
QuickSort(arr,lo,mid-1);
QuickSort(arr,mid+1,hi);
}
}
void Print(struct Stk *stack)
{
for(int i = 0;i < stack->len;i++){
printf("%d ",stack->arr[i]);
}
printf("\n");
}
//n-数组长度,sum剩余要求的和,递归遍历时从k索引开始遍历到n-1,避免重复,stack为栈。
void DFS(int arr[],int n,int sum,int k,struct Stk *stack)
{
for(int i = k;i < n;i++){
if(arr[i] == sum){ //当正好为剩余数的和,就先入栈,再打印,再出栈,最后返回,因为后面的数更大
stack->arr[stack->len] = arr[i];
stack->len++;
Print(stack);
stack->len--;
return;
}
if(arr[i] < sum){ //递归含义,选择后递归,然后退出,再遍历后续元素
stack->arr[stack->len++] = arr[i];
DFS(arr,n,sum-arr[i],i+1,stack);
stack->len--;
int temp = arr[i]; //为了防止重复,在这里退出后,下次入栈的数据要喝刚退出的不一样才行!
while(i<n){
if(arr[i+1]!=temp)
break;
i++;
}
}else{ //当arr[i] > sum 时,就退出,不对后面更大的数进行判断。
break;
}
}
}
int main()
{
int arr[] = {10,1,2,7,6,1,5,1,1,1,1};
int n = sizeof(arr)/sizeof(int);
int sum;
struct Stk stack;
stack.len = 0;
QuickSort(arr,0,n-1);
for(int i = 0;i < n;i++){
printf("%d ",arr[i]);
}
printf("\n");
while(scanf("%d",&sum)){
DFS(arr,n,sum,0,&stack);
}
return 0;
}