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的更多相关文章

  1. 求和问题总结(leetcode 2Sum, 3Sum, 4Sum, K Sum)

    转自  http://tech-wonderland.net/blog/summary-of-ksum-problems.html 前言: 做过leetcode的人都知道, 里面有2sum, 3sum ...

  2. 2Sum,3Sum,4Sum,kSum,3Sum Closest系列

    1).2sum 1.题意:找出数组中和为target的所有数对 2.思路:排序数组,然后用两个指针i.j,一前一后,计算两个指针所指内容的和与target的关系,如果小于target,i右移,如果大于 ...

  3. LeetCode解题报告--2Sum, 3Sum, 4Sum, K Sum求和问题总结

    前言: 这几天在做LeetCode 里面有2sum, 3sum(closest), 4sum等问题, 这类问题是典型的递归思路解题.该这类问题的关键在于,在进行求和求解前,要先排序Arrays.sor ...

  4. 秒杀 2Sum 3Sum 4Sum 算法题

    2 Sum 这题是 Leetcode 的第一题,相信大部分小伙伴都听过的吧. 作为一道标着 Easy 难度的题,它真的这么简单吗? 我在之前的刷题视频里说过,大家刷题一定要吃透一类题,为什么有的人题目 ...

  5. 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 ...

  6. LeetCode Two Sum&Two Sum II - Input array is sorted&3Sum&4Sum 一锅煮题解

    文章目录 Two Sum Two Sum II 3Sum 4Sum Two Sum 题意 给定一个数组,和指定一个目标和.从数组中选择两个数满足和为目标和.保证有且只有一个解.每个元素只可以用一次. ...

  7. 3Sum,4Sum问题

    //三数和为0的问题.要求去重,并且输出数字有序.public List<List<Integer>> threeSum(int[] nums) { Arrays.sort(n ...

  8. lintcode 最长上升连续子序列 II(二维最长上升连续序列)

    题目链接:http://www.lintcode.com/zh-cn/problem/longest-increasing-continuous-subsequence-ii/ 最长上升连续子序列 I ...

  9. CPU相关知识---物理CPU数、物理核数、逻辑核数、逻辑CPU数 ?

    一.物理CPU数.物理核数.逻辑核数.逻辑CPU数 相互关系??? 物理CPU数 ---> 每个物理CPU对应物理核数 ---> (每个物理核数对应逻辑核数)物理CPU对应逻辑核数 --- ...

随机推荐

  1. php基础知识(1)

    1.判断变量是否存在isset() $v1="a"; if(!isset($v1)){ echo "变量存在"; }else{ echo "变量不存在 ...

  2. 细说OpenSessionInView问题

    [环境参数] 环境:SSH框架 [问题描述]  NoSession问题 HibernateTemplate对象提供的方法如果使用“延迟加载”,Session对象的管理不受开发者控制,此时如果在表现层获 ...

  3. svn's tree conflict

    [svn's tree conflict] A tree conflict occurs when a developer moved/renamed/deleted a file or folder ...

  4. HDOJ_1010 Tempter of the Bone

    http://acm.hdu.edu.cn/showproblem.php?pid=1010 奇偶剪枝:可以把map看成这样: 0 1 0 1 0 1 1 0 1 0 1 0 0 1 0 1 0 1 ...

  5. 自己制作 SPx N合1 自动安装盘(x86)

    来处"xinso" 一.制作方法: 以技嘉和惠普为例作,其它的可以如法泡制及变通: 1.复制一份最常用的 OEM XP,例如技嘉,到D:\1TO2 2.在 D:\ 创造一个 HP ...

  6. MPMoviePlayerController 视频播放器—IOS开发

    MPMoviePlayerController 与AVAudioPlayer有点类似,前者播放视频,后者播放音频,不过也有很大不同,MPMoviePlayerController 可以直接通过远程UR ...

  7. HDU 1712 ACboy needs your help (分组背包模版题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1712 有n门课,和m天时间.每门课上不同的天数有不同的价值,但是上过这门课后不能再上了,求m天里的最大 ...

  8. chrome emulator use-agent 设置 chrom模拟手机客户端

    谷歌升级以后,发现找不到use-agent设置了 在Element 下点击ESC 出现console,再点击Emulation就出现了

  9. ASP.NET MVC- HtmlHelper的用法

    在ASP.NET MVC框架中没有了自己的控件,页面显示完全就回到了写html代码的年代.还好在asp.net mvc框架中也有自带的HtmlHelper和UrlHelper两个帮助类.另外在MvcC ...

  10. Opencv2系列学习笔记10(提取连通区域轮廓)

    连通区域指的是二值图像中相连像素组成的形状.而内.外轮廓的概念及opencv1中如何提取二值图像的轮廓见我的这篇博客:http://blog.csdn.net/lu597203933/article/ ...