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 a, b, c 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 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] ]
找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; }
持续更新...