july 大神有个程序员编程艺术系列,第五章《寻找和为定值的多个数》,现在我们站在大牛的肩膀上,对leetcode上n个数求和的系列问题做个阶段性总结。
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].
http://blog.csdn.net/gatieme/article/details/50596965
时间复杂度O(N),空间复杂度O(N)
暴力穷举的办法我们就不说了任选两个数判断和是否为输入即可
a[i]在序列中,如果a[i]+a[k]=sum的话,那么sum-a[i](a[k])也必然在序列中,举个例子,如下:
原始序列:1、2、4、7、11、15
用输入数字15 减一下各个数,得到对应的
序列为:
对应序列:14、13、11、8、4、0
第一个数组以一指针i从数组最左端开始向右扫描,第二个数组以一指针j 从数组最右端开始向左扫描,如果下面出现了和上面一样的数,即a[*i]=a[*j],就找出这俩个数来了。如上,i,j最终在第一个,和第二个序列中找到了相同的数4 和11,所以符合条件的两个数,即为4+11=15。
然后用两个指针i,j,各自指向数组的首尾
两端,令i=0,j=n-1,然后i++,j–,逐次判断a[i]+a[j]?=sum,如果某一刻a[i]+a[j]>sum,
则要想办法让sum 的值减小,所以此刻i 不动,j–,如果某一刻a[i]+a[j]
// leetcode1-2Sum.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
//进阶解法–基于排序O(nlogn)
#include
#include
#define DEBUG
///////////////////////////////////////////////////////////////////////////
///
/// 快速排序--QuickSort
/// http://www.cnblogs.com/RootJie/archive/2012/02/13/2349649.html
///
///////////////////////////////////////////////////////////////////////////
#include
#include
#define MAX_SIZE 20000
#define SWAP(x, y) {int t=x; x=y; y=t;}
void QuickSort(int *array, int left, int right);
int Partition(int *array, int left, int right);
int position[MAX_SIZE]; // 用于存储位置信息
void InitPosion(int *position, int length)
{
for (int pos = 0; pos < length; pos++)
{
position[pos] = pos + 1;
}
}
int Partition(int *array, int left, int right)
{
int pivot = array[left];
while (left < right)
{
while (left < right && array[right] >= pivot)
{
--right;
}
SWAP(array[left], array[right]);
SWAP(position[left], position[right]);
while (left < right && array[left] <= pivot)
{
++left;
}
SWAP(array[right], array[left]);
SWAP(position[left], position[right]);
}
return left;
}
void QuickSort(int *array, int left, int right)
{
int pivot;
if (left < right)
{
pivot = Partition(array, left, right);
QuickSort(array, left, pivot - 1);
QuickSort(array, pivot + 1, right);
}
}
int cmp(const void *left, const void *right)
{
int *left_num = (int *)left;
int *right_num = (int *)right;
return (*left_num - *right_num);
//qsort(nums, numsSize, sizeof(nums[0]), cmp);
}
int* twoSum(int* nums, /* the pointer which point to the array */
int numsSize, /* the size of the array */
int target) /* the sum of the two num */
{
//qsort(nums, numsSize, sizeof(nums[0]), cmp);
InitPosion(position, numsSize);
#ifdef DEBUG
printf("Before Quick Sort : \n");
printf("Array : ");
for (int pos = 0; pos < numsSize; pos++)
{
printf("%3d", nums[pos]);
}
printf("\n");
printf("Position : ");
for (int pos = 0; pos < numsSize; pos++)
{
printf("%3d", position[pos]);
}
printf("\n");
#endif
QuickSort(nums, 0, numsSize - 1);
#ifdef DEBUG
printf("After Quick Sort : \n");
printf("Array : ");
for (int pos = 0; pos < numsSize; pos++)
{
printf("%3d", nums[pos]);
}
printf("\n");
printf("Position : ");
for (int pos = 0; pos < numsSize; pos++)
{
printf("%3d", position[pos]);
}
printf("\n");
#endif
int *answer = (int *)malloc(sizeof(int) * 2);
int left = 0, right = numsSize - 1, sum;
while (left < right)
{
sum = nums[left] + nums[right];
#ifdef DEBUG
printf("[%d, %d], %d + %d = %d\n",
left, right,
nums[left], nums[right], sum);
#endif
if (sum == target)
{
#ifdef DEBUG
printf("[%d, %d], %d + %d = %d\n",
left, right,
nums[left], nums[right], target);
#endif
break;
}
else if (sum < target)
{
#ifdef DEBUG
printf("[%d, %d], %d + %d = %d\n",
left, right,
nums[left], nums[right], target);
#endif
left++;
}
else if (sum > target)
{
#ifdef DEBUG
printf("[%d, %d], %d + %d = %d\n",
left, right,
nums[left], nums[right], target);
#endif
right--;
}
}
if (position[left] < position[right])
{
answer[0] = position[left];
answer[1] = position[right];
}
else
{
answer[0] = position[right];
answer[1] = position[left];
}
return answer;
}
#ifdef DEBUG
int main()
{
int nums[5] = { -1, -2, -3, -4, -5 };
int *answer = NULL;
answer = twoSum(nums, 5, -8);
printf("[%d, %d]\n", answer[0], answer[1]);
}
#endif
class Solution:
def twoSum(self, num, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
# python中字典dict类似于map的
dict = {}
for i in range(len(num)): # 对于每一个num
# 判断target - num[i]在不在在字典中
if dict.get(target - num[i], None) == None: #如果不在
dict[num[i]] = i # 将该数存入字典中
else:
# 否则这两个数的和为target, 则返回
return (dict[target - num[i]] , i )
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]
]
思路:
- 1,先按照由小到大把数组排序
- 2,循环取第i位,数值a[i], 后面剩余的由旁边向中间扫描,看是否符合 a[m]+a[n] == -a[i],如果a[m]+a[n]>-a[i],则向右边移动m,如果小于则向左边移动n
典型c++解法如下:
class Solution
{
public:
vector<vector<int>> threeSum(vector<int>& nums)
{
vector<vector<int> >result;
std::sort(nums.begin(), nums.end());
for (unsigned int i = 0; i < nums.size(); i++)
{
int target = -nums[i];
int front = i + 1;
int back = nums.size() - 1;
while (front < back)
{
int sum = nums[front] + nums[back];
if (sum < target)
front++;
else if (sum > target)
back--;
else
{
vector<int> triplet(3, 0);
triplet[0] = nums[i];
triplet[1] = nums[front];
triplet[2] = nums[back];
result.push_back(triplet);
//处理有两个同样的数的情况
while (front < back && nums[front] == triplet[1])front++;
while (front < back && nums[back] == triplet[2])back--;
}
}
//处理有两个同样的数的情况
while (i + 1 < nums.size() && nums[i + 1] == nums[i]) i++;
}
return result;
}
};
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).
class Solution
{
public:
int threeSumClosest(vector<int>& nums,int target)
{
sort(nums.begin(),nums.end());
int result = nums[0]+nums[1]+nums[2];
for(int i =0;i2;i++)
{
int j = i+1,k=nums.size()-1;
while(jint num = nums[i] + nums[j] + nums[k];
if(abs(num - target) < abs(res - target)) res = num;
if(num < target) j++;
else k--;
}
}
return result;
}
};
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]
]
// O(n^3)
class Solution {
public:
vector<vector<int> > fourSum(vector<int> &nums, int target) {
set<vector<int> > res;
sort(nums.begin(), nums.end());
for (int i = 0; i < int(nums.size() - 3); ++i) {
for (int j = i + 1; j < int(nums.size() - 2); ++j) {
int left = j + 1, right = nums.size() - 1;
while (left < right) {
int sum = nums[i] + nums[j] + nums[left] + nums[right];
if (sum == target) {
vector<int> out;
out.push_back(nums[i]);
out.push_back(nums[j]);
out.push_back(nums[left]);
out.push_back(nums[right]);
res.insert(out);
++left; --right;
} else if (sum < target) ++left;
else --right;
}
}
}
return vector<vector<int> > (res.begin(), res.end());
}
};
https://www.jianshu.com/p/3d1791cfba53
http://blog.csdn.net/XingKong_678/article/details/50894322
http://blog.csdn.net/yuanwei1314/article/details/42963229
输入两个整数n 和m,从数列1,2,3…….n 中随意取几个数,
使其和等于m ,要求将其中所有的可能组合列出来。
// 21 题递归方法
//copyright@ July && yansha
//July、yansha,updated。
#include
#include
using namespace std;
list<int>list1;
void find_factor(int sum, int n)
{
// 递归出口
if(n <= 0 || sum <= 0)
return;
// 输出找到的结果
if(sum == n)
{
// 反转list
list1.reverse();
for(list<int>::iterator iter = list1.begin(); iter != list1.end(); iter++)
cout << *iter << " + ";
cout << n << endl;
list1.reverse();
list1.push_front(n); //典型的01 背包问题
find_factor(sum-n, n-1); //放n,n-1 个数填满sum-n
list1.pop_front();
find_factor(sum, n-1); //不放n,n-1 个数填满sum
}
int main()
{
int sum, n;
cout << "请输入你要等于多少的数值sum:" << endl;
cin >> sum;
cout << "请输入你要从1.....n 数列中取值的n:" << endl;
cin >> n;
cout << "所有可能的序列,如下:" << endl;
find_factor(sum,n);
return 0;
}