[LeetCode]sum合集

LeetCode很喜欢sum,里面sum题一堆。

1.Two Sum

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
 1 /**
 2  * Note: The returned array must be malloced, assume caller calls free().
 3  */
 4 int* twoSum(int* nums, int numsSize, int target) {
 5     int* ret = (int*)malloc(2*sizeof(int));
 6     int j = 1;
 7     for(int i = 0;i < numsSize - 1;){
 8         if(nums[i] + nums[j] == target){
 9             ret[0] = i;
10             ret[1] = j;
11             break;
12         }
13         j++;
14         if(j == numsSize){
15             i++;
16             j = i + 1;
17         }
18     }
19     return ret;
20 }

用hash_map使其复杂度减小到O(n)

vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> ret;
        hash_map<int, int>arr;
        for (int i = 0; i < nums.size(); i++){
            int rem = target - nums[i];
            if (arr.find(rem) != arr.end()){
                ret.push_back(i);
                ret.push_back(arr.at(rem));
                return ret;
            }
            arr[nums[i]] = i;
        }
        return ret;
    }

2.3Sum

题目:

Given an array S of n integers, are there elements abc in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note: The solution set must not contain duplicate triplets.

For example, given array S = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

找3个数和为0的所有不同组合,数组元素只能用1次

1.不知道具体有多少种可能,用链表来存储,再转成数组

2.暴力搜索,可以先排序,加快速度

3.注意跳过重复情况

 1 /*************************************************
 2 Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
 3 Note: The solution set must not contain duplicate triplets.
 4 For example, given array S = [-1, 0, 1, 2, -1, -4],
 5 A solution set is:
 6 [
 7   [-1, 0, 1],
 8   [-1, -1, 2]
 9 ]
10 *************************************************/
11 #include<stdio.h>
12 #include<stdlib.h>
13 
14 int cmp(const void *a , const void *b){
15     return *(int *)a > *(int *)b ? 1 : -1;
16 }
17 
18 struct linklist{
19     int *val;
20     struct linklist *next;
21 };
22 
23 /**
24  * Return an array of arrays of size *returnSize.
25  * Note: The returned array must be malloced, assume caller calls free().
26  */
27 int** threeSum(int* nums, int numsSize, int* returnSize) {
28     struct linklist *ts = NULL;
29     int i,n = 0,head,tail,sum = 0;
30         //排序加快搜索
31         qsort(nums,numsSize,sizeof(int),cmp);
32         //i、head、tail三个指针,暴力搜索所有可能
33         for(i = 0;i < numsSize;i++){
34             head = i + 1;
35             tail = numsSize - 1;
36             while (head < tail) {
37                 sum = nums[i] + nums[head] + nums[tail];
38                 if(sum == 0){//找到一种可能
39                     n++;
40                     struct linklist *p = (struct linklist *)malloc(sizeof(struct linklist));
41                     p->val = (int *)malloc(3*sizeof(int));
42                     p->val[0] = nums[i];
43                     p->val[1] = nums[head];
44                     p->val[2] = nums[tail];
45                     p->next = ts;
46                     ts = p;
47                     head++;
48                     tail--;
49                     while(nums[head] == nums[head - 1])head++;//跳过重复的情况
50                     while(nums[tail] == nums[tail + 1])tail--;
51                 }else if(sum > 0){//过大
52                     while(nums[tail] == nums[tail - 1])tail--;
53                     tail--;
54                 }else{//过小
55                     while(nums[head] == nums[head + 1])head++;
56                     head++;
57                 }
58             }
59             while(nums[i] == nums[i + 1])i++;//跳过重复的情况
60         }
61 
62         struct linklist *p = NULL;
63         int **as = (int **)malloc(n*sizeof(int *));
64         for(i = 0;i < n;i++)
65             as[i] = (int *)malloc(3*sizeof(int));
66         i = 0;
67         while(ts != NULL){
68             as[i][0] = ts->val[0];
69             as[i][1] = ts->val[1];
70             as[i++][2] = ts->val[2];
71             p = ts;
72             ts = ts->next;
73             p->next = NULL;
74             free(p->val);
75             free(p);
76         }
77 
78        *returnSize = n;
79        return as;
80 }
81 
82 int main(){
83     int a[] = {-1,0,1,2,-1,-4};
84     int n = 0;
85     int **as = threeSum(a,sizeof(a)/sizeof(int),&n);
86     printf("%d
",n);
87     for(int i = 0;i < n;i++){
88         for(int j = 0;j < 3;j++)
89             printf("%d ",as[i][j]);
90         printf("
");
91     }
92 
93     for(int i = 0;i < n;i++){
94         free(as[i]);
95     }
96 }

3.3Sum Closest

题目:

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

    For example, given array S = {-1 2 1 -4}, and target = 1.

    The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

找3个数的和最接近目标数的组合。

 1 /***************************************************************************************************
 2 Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
 3     For example, given array S = {-1 2 1 -4}, and target = 1.
 4     The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
 5 **************************************************************************************************/
 6 #include <stdio.h>
 7 #include <stdlib.h>
 8 
 9 int cmp(const void *a , const void *b){
10     return *(int *)a > *(int *)b ? 1 : -1;
11 }
12 
13 int threeSumClosest(int* nums, int numsSize, int target) {
14         int bestdif = 2147483647,bestsum;
15     int dif,sum,i,head,tail;
16     
17     qsort(nums,numsSize,sizeof(int),cmp);
18     
19     for(i = 0;i < numsSize;i++){
20         head = i + 1;
21         tail = numsSize - 1;
22         while(head < tail){
23             sum = nums[i] + nums[head] + nums[tail];
24             dif = sum - target;//求差值
25             if(dif == 0)return sum;
26             else if(dif > 0){
27                 tail--;
28                 while(nums[tail] == nums[tail + 1])tail--;
29             }else{
30                 head++;
31                 while(nums[head] == nums[head - 1])head++;
32             }
33             dif = abs(dif);
34             if(dif < bestdif){//比较是否比已知的结果好
35                 bestdif = dif;
36                 bestsum = sum;
37             }
38         }
39         while(nums[i] == nums[i + 1])i++;
40     }
41     return bestsum;
42 }
43 
44 void main(){
45     int nums[] = {-1,2,1,-4,0};
46     int target = 1;
47     int sum = threeSumClosest(nums,sizeof(nums)/sizeof(int),target);
48     printf("%d
",sum);
49 }

4.4Sum

题目:

Given an array S of n integers, are there elements abc, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note: The solution set must not contain duplicate quadruplets.

For example, given array S = [1, 0, -1, 0, -2, 2], and target = 0.

A solution set is:
[
  [-1,  0, 0, 1],
  [-2, -1, 1, 2],
  [-2,  0, 0, 2]
]

找4个数和为目标数的所有不同组合,数组元素只能用1次

接着暴力搜索。

/***************************************************************************************************
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note: The solution set must not contain duplicate quadruplets.
For example, given array S = [1, 0, -1, 0, -2, 2], and target = 0.
A solution set is:
[
  [-1,  0, 0, 1],
  [-2, -1, 1, 2],
  [-2,  0, 0, 2]
]
***************************************************************************************************/
#include<stdio.h>

int cmp(const void *a , const void *b){
    return *(int *)a > *(int *)b ? 1 : -1;
}

struct linklist{
    int *val;
    struct linklist *next;
};

/**
 * Return an array of arrays of size *returnSize.
 * Note: The returned array must be malloced, assume caller calls free().
 */
int** fourSum(int* nums, int numsSize, int target, int* returnSize) {
        struct linklist *fs = NULL;
    int i,j,head,tail,dif = 0,length = 0;
    
    qsort(nums,numsSize,sizeof(int),cmp);//排序
    
    //i,j,head,tail四个游标,暴力搜索
    for(i = 0;i < numsSize;i++){
        for(j = i + 1;j < numsSize;j++){
            head = j + 1;//head从j+1开始
            tail = numsSize - 1;
            while(head < tail){
                dif = nums[i] + nums[j] + nums[head] + nums[tail] - target;
                if(dif == 0){
                    length++;
                    struct linklist *p = (struct linklist *)malloc(sizeof(struct linklist));
                        p->val = (int *)malloc(4*sizeof(int));
                        p->val[0] = nums[i];
                        p->val[1] = nums[j];
                        p->val[2] = nums[head++];
                        p->val[3] = nums[tail--];
                        p->next = fs;
                        fs = p;
                        while(nums[head] == nums[head - 1])head++;
                        while(nums[tail] == nums[tail + 1])tail--;
                }else if(dif > 0){//过大
                    while(nums[tail] == nums[tail - 1])tail--;
                    tail--;
                }else{//过小
                    while(nums[head] == nums[head + 1])head++;
                    head++;
                }
            }
            while(nums[j] == nums[j + 1])j++;
        }
        while(nums[i] == nums[i + 1])i++;
    }
    
    int **ret = (int **)malloc(length*sizeof(int *));
    struct linklist *p = NULL;
    i = 0;
    while(fs != NULL){
        p = fs;
        fs = fs->next;
        p->next = NULL;
        ret[i] = (int *)malloc(4*sizeof(int));
        ret[i][0] = p->val[0];
        ret[i][1] = p->val[1];
        ret[i][2] = p->val[2];
        ret[i++][3] = p->val[3];
        free(p->val);
        free(p);
    }
    
    *returnSize = length;
    return ret;
}

void main(){
    int a[] = {-1,0,1,2,-1,-4,0};
    int n = 0,target = 0;
    int **as = fourSum(a,sizeof(a)/sizeof(int),target,&n);
    printf("%d
",n);
    for(int i = 0;i < n;i++){
        for(int j = 0;j < 4;j++)
            printf("%d ",as[i][j]);
        printf("
");
    }

    for(int i = 0;i < n;i++){
        free(as[i]);
    }
}

5.Combination Sum

题目:

Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.

The same repeated number may be chosen from C unlimited number of times.

Note:

  • All numbers (including target) will be positive integers.
  • The solution set must not contain duplicate combinations.

For example, given candidate set [2, 3, 6, 7] and target 7
A solution set is: 

[
  [7],
  [2, 2, 3]
]

从数组中找和是目标数的所有组合,数组元素可以使用多次

用递归的思想求解:首先排序,然后搜索数组所有元素,目标数减去当前元素作为新的目标数,再递归搜索新的目标数,知道目标数为0.

1.多种不同组合中可能有部分元素重合,所以,搜索到一种结果后,还要继续搜索。

2.找到符合情况的组合后才能给数组分配大小,所以要记录递归的层数,返回时,每层给数组附上各自的值。

3.注意链表头特殊处理。

/*******************************************************************************
Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
The same repeated number may be chosen from C unlimited number of times.
Note:
All numbers (including target) will be positive integers.
The solution set must not contain duplicate combinations.
For example, given candidate set [2, 3, 6, 7] and target 7, 
A solution set is: 
[
  [7],
  [2, 2, 3]
]
*******************************************************************************/
#include<stdio.h>
#include<stdbool.h>

struct linklist{
    int *val;//存储符合要求的数的组合
    int size;//数组大小
    struct linklist *next;
};

int cmp(const void *a , const void *b){
    return *(int *)a > *(int *)b ? 1 : -1;
}

struct linklist *getTargetArray(int *candidates,int candidatesSize,int surplus,int start,int length){
    struct linklist *head = NULL;
    struct linklist *tail = head;
    int subStrSize;
    //递增排序,目标数比当前值还小,后面的就更加不可能了
    for(int i = start;i < candidatesSize && surplus >= candidates[i];i++){
        if(surplus - candidates[i] == 0){//找到一种情况
            struct linklist *p = (struct linklist *)malloc(sizeof(struct linklist));
            p->size = length + 1;
            p->val = (int *)malloc(p->size*sizeof(int));
            p->val[length] = candidates[i];
            p->next = head;
            head = p;
        }else{
            if(tail == NULL){//第一个符合情况的出现时,得到链表头
                tail = getTargetArray(candidates,candidatesSize,surplus - candidates[i],i,length + 1);
                if(tail != NULL){//如果找到了符合的情况,添加当前的数
                    head = tail;
                    tail->val[length] = candidates[i];
                }
            }else{
                tail->next = getTargetArray(candidates,candidatesSize,surplus - candidates[i],i,length + 1);
            }
            while(tail != NULL && tail->next != NULL){
                tail->next->val[length] = candidates[i];
                tail = tail->next;
            }
        }
    }

    return head;
}

/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *columnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */
int** combinationSum(int* candidates, int candidatesSize, int target, int** columnSizes, int* returnSize) {
        struct linklist *cs = NULL;
        struct linklist *tail = cs;
        int **retStr = NULL;
        int *subStr = NULL;
        int subStrSize,count = 0;

    qsort(candidates,candidatesSize,sizeof(int),cmp);

        //递增排序,目标数比当前值还小,后面的就更加不可能了
        for(int i = 0;i < candidatesSize && target >= candidates[i];i++){
            if(target - candidates[i] == 0){
                struct linklist *p = (struct linklist *)malloc(sizeof(struct linklist));
                p->size = 1;
                p->val = (int *)malloc(sizeof(int));
                p->val[0] = candidates[i];
                p->next = cs;
                cs = p;
                count++;
            }else{
                if(tail == NULL){//第一个符合情况的出现时,得到链表头
                    tail = getTargetArray(candidates,candidatesSize,target - candidates[i],i,1);
                    if(tail != NULL){//如果找到了符合的情况,添加当前的数
                        cs = tail;
                        tail->val[0] = candidates[i];
                        count++;
                    }
                }else{
                    tail->next = getTargetArray(candidates,candidatesSize,target - candidates[i],i,1);
                }
                while(tail != NULL && tail->next != NULL){//如果找到了符合的情况,添加当前的数
                    tail->next->val[0] = candidates[i];
                    tail = tail->next;
                    count++;
                }
            }
        }

        retStr = (int **)malloc(count*sizeof(int *));
        *columnSizes = (int *)malloc(count*sizeof(int));
    struct linklist *p = NULL;
    int i = 0;
    while(cs != NULL){
        p = cs;
        cs = cs->next;
        p->next = NULL;
        retStr[i] = (int *)malloc(p->size*sizeof(int));
        columnSizes[0][i] = p->size;
        for(int j = 0;j < p->size;j++)retStr[i][j] = p->val[j];
        free(p->val);
        free(p);
        i++;
    }

    *returnSize = count;
    return retStr;
}

void main(){
    int a[] = {2, 3};
    int target = 6,size;
    int *length = NULL;
    int **ret = combinationSum(a,sizeof(a)/sizeof(int),target,&length,&size);
    printf("%d
",size);
    for(int i = 0;i < size;i++){
        for(int j = 0;j < length[i];j++){
            printf("%d ",ret[i][j]);
        }
        free(ret[i]);
        printf("
");
    }

    free(length);
    free(ret);
}

6.Combination Sum II

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.
  • 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]
]

从数组中找和是目标数的所有组合,数组元素可以使用1次

  1 /***************************************************************************************************
  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.
  3 Each number in C may only be used once in the combination.
  4 Note:
  5 All numbers (including target) will be positive integers.
  6 The solution set must not contain duplicate combinations.
  7 For example, given candidate set [10, 1, 2, 7, 6, 1, 5] and target 8, 
  8 A solution set is: 
  9 [
 10   [1, 7],
 11   [1, 2, 5],
 12   [2, 6],
 13   [1, 1, 6]
 14 ]
 15 ***************************************************************************************************/
 16 #include<stdio.h>
 17 #include<stdbool.h>
 18 
 19 struct linklist{
 20     int *val;
 21     int size;
 22     struct linklist *next;
 23 };
 24 
 25 int cmp(const void *a , const void *b){
 26     return *(int *)a > *(int *)b ? 1 : -1;
 27 }
 28 
 29 struct linklist *getTargetArray(int *candidates,int candidatesSize,int surplus,int start,int length){
 30     struct linklist *head = NULL;
 31     struct linklist *tail = head;
 32     int subStrSize;
 33     for(int i = start + 1;i < candidatesSize && surplus >= candidates[i];i++){
 34         if(surplus - candidates[i] == 0){
 35             struct linklist *p = (struct linklist *)malloc(sizeof(struct linklist));
 36             p->size = length + 1;
 37             p->val = (int *)malloc(p->size*sizeof(int));
 38             p->val[length] = candidates[i];
 39             p->next = head;
 40             head = p;
 41         }else{
 42             if(tail == NULL){
 43                 tail = getTargetArray(candidates,candidatesSize,surplus - candidates[i],i,length + 1);
 44                 if(tail != NULL){
 45                     head = tail;
 46                     tail->val[length] = candidates[i];
 47                 }
 48             }else{
 49                 tail->next = getTargetArray(candidates,candidatesSize,surplus - candidates[i],i,length + 1);
 50             }
 51             while(tail != NULL && tail->next != NULL){
 52                 tail->next->val[length] = candidates[i];
 53                 tail = tail->next;
 54             }
 55         }
 56         while(candidates[i] == candidates[i+1])i++;
 57     }
 58 
 59     return head;
 60 }
 61 
 62 /**
 63  * Return an array of arrays of size *returnSize.
 64  * The sizes of the arrays are returned as *columnSizes array.
 65  * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 66  */
 67 int** combinationSum2(int* candidates, int candidatesSize, int target, int** columnSizes, int* returnSize) {
 68     struct linklist *cs = NULL;
 69         struct linklist *tail = cs;
 70         int **retStr = NULL;
 71         int *subStr = NULL;
 72         int subStrSize,count = 0;
 73 
 74     qsort(candidates,candidatesSize,sizeof(int),cmp);
 75 
 76         for(int i = 0;i < candidatesSize && target >= candidates[i];i++){
 77             if(target - candidates[i] == 0){
 78                 struct linklist *p = (struct linklist *)malloc(sizeof(struct linklist));
 79                 p->size = 1;
 80                 p->val = (int *)malloc(sizeof(int));
 81                 p->val[0] = candidates[i];
 82                 p->next = cs;
 83                 cs = p;
 84                 count++;
 85             }else{
 86                 if(tail == NULL){
 87                     tail = getTargetArray(candidates,candidatesSize,target - candidates[i],i,1);
 88                     if(tail != NULL){
 89                         cs = tail;
 90                         tail->val[0] = candidates[i];
 91                         count++;
 92                     }
 93                 }else{
 94                     tail->next = getTargetArray(candidates,candidatesSize,target - candidates[i],i,1);
 95                 }
 96                 while(tail != NULL && tail->next != NULL){
 97                     tail->next->val[0] = candidates[i];
 98                     tail = tail->next;
 99                     count++;
100                 }
101             }
102             while(candidates[i] == candidates[i+1])i++;
103         }
104 
105         retStr = (int **)malloc(count*sizeof(int *));
106         *columnSizes = (int *)malloc(count*sizeof(int));
107     struct linklist *p = NULL;
108     int i = 0;
109     while(cs != NULL){
110         p = cs;
111         cs = cs->next;
112         p->next = NULL;
113         retStr[i] = (int *)malloc(p->size*sizeof(int));
114         columnSizes[0][i] = p->size;
115         for(int j = 0;j < p->size;j++)retStr[i][j] = p->val[j];
116         free(p->val);
117         free(p);
118         i++;
119     }
120 
121     *returnSize = count;
122     return retStr;
123 }
124 
125 void main(){
126     int a[] = {2,2,2};
127     int target = 4,size;
128     int *length = NULL;
129     int **ret = combinationSum2(a,sizeof(a)/sizeof(int),target,&length,&size);
130     printf("%d
",size);
131     for(int i = 0;i < size;i++){
132         for(int j = 0;j < length[i];j++){
133             printf("%d ",ret[i][j]);
134         }
135         free(ret[i]);
136         printf("
");
137     }
138 
139     free(length);
140     free(ret);
141 }

题目:Combination Sum III

从1-9中找k个不同的数保证其和为n。返回所有符合要求的组合。

思路:

通过递归找k个元素求和,和不等于n或个数大于k,则回溯。

void LeetCode::combinationSum(vector<vector<int>>&result, vector<int>& arr, int k, int n){
    if (arr.size() == k && !n){//找到一个可行的结果
        result.push_back(arr);
        return;
    }
    if (arr.size() >= k)return;//没有合适的
    int i = arr.size() ? arr.at(arr.size() - 1) + 1: 1;//从最后一个元素的后一个数开始
    for (; i <= 9 && n - i >= 0; ++i){
        arr.push_back(i);//装入
        combinationSum(result, arr, k, n - i);//递归找下一个
        arr.pop_back();
    }
}

vector<vector<int>> LeetCode::combinationSum3(int k, int n){
    vector<vector<int>>result;
    vector<int>arr;
    combinationSum(result, arr, k, n);
    return result;
}

持续更新...

原文地址:https://www.cnblogs.com/yeqluofwupheng/p/6661410.html