LeetCode | Combination Sum II(元素的和---2)

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 (a1a2, … , 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;
}


点赞