2sum、3sum、4sum以及任意连续的数的和为sum、任意连续或者不连续的数的和为sum
2sum
如果数组是无序的,先排序(n*logn),然后用两个指针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]<sum,则要想办法让sum 的值增大,所以此刻i++,j 不动。所以,数组无序的时候,时间复杂度最终为O(n*logn+n)=O(n*logn),若原数组是有序的,则不需要事先的排序,直接O(n)搞定,且空间复杂度还是O(1),此思路是相对于上述所有思路的一种改进。
Pair findSum(int *s,int n,int x)
{
//sort(s,s+n); 如果数组非有序的,那就事先排好序O(N*logN)
int *begin=s;
int *end=s+n-;
while(begin<end) //俩头夹逼,或称两个指针两端扫描法,很经典的方法,O(N)
{
if(*begin+*end>x)
{
--end;
}
else if(*begin+*end<x)
{
++begin;
}
else
{
return Pair(*begin,*end);
} }
return Pair(-,-);
}
3sum
vector<vector<int> > threeSum(vector<int> &num) {
if(num.empty())
return vector<vector<int> >();
sort(num.begin(),num.end());
vector<vector<int> > ret;
vector<int> tmp;
int n=num.size();
for(int i=;i<n-;i++)
{
if(i>&&num[i]==num[i-]) continue;//防止存在重复的元素
int target=-num[i];
int j=i+;
int k=n-;
while(j<k)
{
if(j<k&&k<n-&&num[k]==num[k+])
{
k--;
continue;
}
if(num[j]+num[k]==target)
{
tmp={num[i],num[j],num[k]};
ret.push_back(tmp);
j++;
k--;
}
else if(num[j]+num[k]<target)
{
j++;
}
else if(num[j]+num[k]>target)
k--;
}
}
return ret;
}
4sum
vector<vector<int> > fourSum(vector<int> &num,int target)
{
if(num.empty())
return vector<vector<int> >();
sort(num.begin(),num.end());
vector<vector<int> > ret;
int n=num.size();
int i,j;
for(i=; i<n-; i++)
{
//只保留第一个不重复的,其余的都删了,因为left会选择重复的
if(i>=&&num[i]==num[i-])
continue;
for(j=n-; j>i+; j--)
{
//只保留最后一个不重复的,其余的都删了,因为right会选择重复的
if(j<n-&&num[j+]==num[j])
continue;
int left=i+;
int right=j-;
vector<int> tmp;
while(left<right)
{
//只保留最后一个不重复的,其余的都删了,因为left会选择重复的
if(right<j-&&num[right]==num[right+])
{
right--;
continue;
}
if(num[i]+num[j]+num[left]+num[right]==target)
{
tmp= {num[i],num[left],num[right],num[j]};
ret.push_back(tmp);
left++;
right--;
}
else if(num[i]+num[j]+num[left]+num[right]<target)
left++;
else if(num[i]+num[j]+num[left]+num[right]>target)
right--;
}
}
}
return ret;
}
任意连续数的和为sum(假设至少存在两个数)
void sum(int sum,int n)
{
if(sum<||n<)
return -;
int cursum=;
cursum=+;
int i=,j=;
while(j<=n)
{
if(cursum==sum)
{
int k=i;
while(k<=j)
{
cout<<k<<' ';
k++;
}
cout<<endl;
cursum-=i;
i++;
}
else if(cursum<sum)
{
j++;
cursum+=j;
}
else if(cursum>sum)
{
cursum-=i;
i++;
}
}
}
任意数的和为sum
用回溯的方法实现:
#include<iostream>
#include<vector>
using namespace std; void findhelper(int m,int n,int start,vector<int> &path)
{
if(m<)
return;
if(m==)
{
for(auto a:path)
cout<<a<<' ';
cout<<endl;
return;
}
for(int i=start; i<=n; ++i)
{
path.push_back(i);
findhelper(m-i,n,i+,path);
path.pop_back();
}
}
void findSum(int m,int n)
{
vector<int> path;
findhelper(m,n,,path);
} int main()
{
findSum(,);
}
用0-1背包法实现:
注意到取n,和不取n个区别即可,考虑是否取第n个数的策略,可以转化为一个只和前n-1个数相关的问题。
- 如果取第n个数,那么问题就转化为“取前n-1个数使得它们的和为sum-n”,对应的代码语句就是sumOfkNumber(sum - n, n - 1);
- 如果不取第n个数,那么问题就转化为“取前n-1个数使得他们的和为sum”,对应的代码语句为sumOfkNumber(sum, n - 1)。
实现代码:
#include<iostream>
#include<vector>
using namespace std; void findhelper(int sum,int n,vector<int> &path)
{
//递归出口
if(sum<=||n<=)
return;
//输出找到的结果
if(sum==n)
{
for(int i=path.size()-; i>=; --i)
cout<<path[i]<<' ';
cout<<n<<endl;
}
path.push_back(n); //典型的01背包问题
findhelper(sum-n,n-,path);//放第n个元素
path.pop_back();
findhelper(sum,n-,path); //不放第n个元素
}
void findSum(int m,int n)
{
vector<int> path;
findhelper(m,n,path);
} int main()
{
findSum(,);
}
存在重复元素时,求和为sum
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std; void helper(vector<int> &num,vector<int> &path,int start,int sum)
{
if(sum==)
{
for(int i=;i<path.size();++i)
cout<<path[i]<<' ';
cout<<endl;
return;
}
if(sum<)
return;
for(int i=start;i<num.size();++i)
{
if(i>start&&num[i]==num[i-])
continue;
path.push_back(num[i]);
helper(num,path,i+,sum-num[i]);
path.pop_back();
}
}
void findSum(vector<int> &num,int sum)
{
vector<int> path;
sort(num.begin(),num.end());
helper(num,path,,sum);
} int main()
{
vector<int> num={,,,,,};
findSum(num,);
}
2sum、3sum、4sum以及任意连续的数的和为sum、任意连续或者不连续的数的和为sum的更多相关文章
- 求和问题总结(leetcode 2Sum, 3Sum, 4Sum, K Sum)
转自 http://tech-wonderland.net/blog/summary-of-ksum-problems.html 前言: 做过leetcode的人都知道, 里面有2sum, 3sum ...
- 2Sum,3Sum,4Sum,kSum,3Sum Closest系列
1).2sum 1.题意:找出数组中和为target的所有数对 2.思路:排序数组,然后用两个指针i.j,一前一后,计算两个指针所指内容的和与target的关系,如果小于target,i右移,如果大于 ...
- LeetCode解题报告--2Sum, 3Sum, 4Sum, K Sum求和问题总结
前言: 这几天在做LeetCode 里面有2sum, 3sum(closest), 4sum等问题, 这类问题是典型的递归思路解题.该这类问题的关键在于,在进行求和求解前,要先排序Arrays.sor ...
- 秒杀 2Sum 3Sum 4Sum 算法题
2 Sum 这题是 Leetcode 的第一题,相信大部分小伙伴都听过的吧. 作为一道标着 Easy 难度的题,它真的这么简单吗? 我在之前的刷题视频里说过,大家刷题一定要吃透一类题,为什么有的人题目 ...
- 6.3Sum && 4Sum [ && K sum ] && 3Sum Closest
3Sum Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find a ...
- LeetCode Two Sum&Two Sum II - Input array is sorted&3Sum&4Sum 一锅煮题解
文章目录 Two Sum Two Sum II 3Sum 4Sum Two Sum 题意 给定一个数组,和指定一个目标和.从数组中选择两个数满足和为目标和.保证有且只有一个解.每个元素只可以用一次. ...
- 3Sum,4Sum问题
//三数和为0的问题.要求去重,并且输出数字有序.public List<List<Integer>> threeSum(int[] nums) { Arrays.sort(n ...
- lintcode 最长上升连续子序列 II(二维最长上升连续序列)
题目链接:http://www.lintcode.com/zh-cn/problem/longest-increasing-continuous-subsequence-ii/ 最长上升连续子序列 I ...
- CPU相关知识---物理CPU数、物理核数、逻辑核数、逻辑CPU数 ?
一.物理CPU数.物理核数.逻辑核数.逻辑CPU数 相互关系??? 物理CPU数 ---> 每个物理CPU对应物理核数 ---> (每个物理核数对应逻辑核数)物理CPU对应逻辑核数 --- ...
随机推荐
- QS之warning message
Multiple message categories are specified as a comma separated list.
- MATLAB将矩阵使用.txt文件格式保存
具体的命令是:用save *.txt -ascii x x为变量 *.txt为文件名,该文件存储于当前工作目录下,再打开就可以 打开后,数据有可能是以指数形式保存的. 看下面这个例子: a =[1 ...
- MapReduce阅读
1.mongodb权威指南6.4章 2.百科:http://baike.baidu.com/link?url=fl9FwgNq7gtFLwJ-GuKsJ25Uk-wnhgDjEwkKd8-5hoIkh ...
- Array.prototype.slice.call
Array.prototype.slice.call(arguments)能将具有length属性的对象转成数组 ,::'age'}; Array.prototype.slice.call(arr); ...
- mysql create table - data_type length -- clwu
mysql create table 时,有时需要指定 data_type length http://dev.mysql.com/doc/refman/5.5/en/create-table.ht ...
- Cocos本地存储LocalStorage
HTML5 LocalStorage 本地存储 //存档 var stopResumeMenu4 = cc.MenuItemFont.create("存档", this.onSav ...
- android get uuid获取uuid
https://github.com/Paldom/UniqueDeviceID protected void getDeviceUUID(){ try { Context context = cor ...
- CST和GMT时间的区别
CST和GMT时间的区别 今天遇到一个奇怪的问题,在服务器端通过 c# 获取当前时间为 Fri Aug 28 09:37:46 CST 2009, 转化为 GMT时间为:28 Aug 2009 01: ...
- 【Visual Studio2010】创建XAML分析插件
最近项目[Silverlight]中的需要实现国际化,需要对所有控件进行一个处理.由于使用了Telerik的控件,只需要去掉原有的Label或者Header属性,然后添加一个资源Key即可.但是在项目 ...
- 异步编程之Generator(1)——领略魅力
异步编程系列教程: (翻译)异步编程之Promise(1)--初见魅力 异步编程之Promise(2):探究原理 异步编程之Promise(3):拓展进阶 异步编程之Generator(1)--领略魅 ...