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-1;
    while(begin<end) //俩头夹逼,或称两个指针两端扫描法,很经典的方法,O(N)
    {
        if(*begin+*end>x)
        {
            --end;
        }
        else if(*begin+*end<x)
        {
            ++begin;
        }
        else
        {
            return Pair(*begin,*end);
        }
        178
    }
    return Pair(-1,-1);
}

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=0;i<n-2;i++)
        {
            if(i>0&&num[i]==num[i-1]) continue;//防止存在重复的元素
            int target=-num[i];
            int j=i+1;
            int k=n-1;
            while(j<k)
            {
                if(j<k&&k<n-1&&num[k]==num[k+1])
                {
                    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=0; i<n-3; i++)
        {
            //只保留第一个不重复的,其余的都删了,因为left会选择重复的
            if(i>=1&&num[i]==num[i-1])
                continue;
            for(j=n-1; j>i+2; j--)
            {
                //只保留最后一个不重复的,其余的都删了,因为right会选择重复的
                if(j<n-1&&num[j+1]==num[j])
                   continue;
                int left=i+1;
                int right=j-1;
                vector<int> tmp;
                while(left<right)
                {
                    //只保留最后一个不重复的,其余的都删了,因为left会选择重复的
                    if(right<j-1&&num[right]==num[right+1])
                    {
                        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<0||n<2)
        return -1;
    int cursum=0;
    cursum=1+2;
    int i=0,j=1;
    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<0)
        return;
    if(m==0)
    {
        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+1,path);
        path.pop_back();
    }
}
void findSum(int m,int n)
{
    vector<int> path;
    findhelper(m,n,1,path);
}

int main()
{
    findSum(15,20);
}
时间: 2024-10-24 06:47:21

2sum、3sum、4sum以及任意连续的数的和为sum、任意连续或者不连续的数的和为sum的相关文章

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

1).2sum 1.题意:找出数组中和为target的所有数对 2.思路:排序数组,然后用两个指针i.j,一前一后,计算两个指针所指内容的和与target的关系,如果小于target,i右移,如果大于,j左移,否则为其中一个解 3.时间复杂度:O(nlgn)+O(n) 4.空间:O(1) 5.代码: void twoSum(vector<int>& nums,int numsSize,int target,vector<vector<int>>& two

输入一个任意位数的的整数, 从个位开始输出每一位的数

题目要求: 输入一个任意位数的的整数, 从个位开始输出每一位的数,  每次输出的一位数可以用%10来取,然后通过把数除10去掉已输出的位 代码如下 #include <stdio.h> int main() { int number; scanf("%d",&number); while(number) { printf("%d ",number%10); number /= 10; } return 0; }

在O(n)时间复杂度内求无序数组中任意两个元素的最大差值,以及存在的组数

题目描述: 求无序数组中任意两个元素的最大差值,以及存在最大差值的组别数. 输入: 输入包含两行,第一行输入一个整数n:第二行n个正整数,用空格隔开. 输出: 输出为一行,包含最大差值,以及存在组别数. 样例输入: 4 4  1  2  1 输出: 3  2 一种实现代码如下(Java版): 1 import java.util.Scanner; 2 /** 3 * 在O(n)时间复杂度内求无序数组中任意两个元素的最大差值,以及存在的组数 4 * @author JiaJoa 5 * 6 */

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

题目链接:http://www.lintcode.com/zh-cn/problem/longest-increasing-continuous-subsequence-ii/ 最长上升连续子序列 II 给定一个整数矩阵(其中,有 n 行, m 列),请找出矩阵中的最长上升连续子序列.(最长上升连续子序列可从任意行或任意列开始,向上/下/左/右任意方向移动). 样例 给定一个矩阵 [ [1 ,2 ,3 ,4 ,5], [16,17,24,23,6], [15,18,25,22,7], [14,1

杭电1003 Max Sum 【连续子序列求最大和】

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1003 题目意思: 即给出一串数据,求连续的子序列的最大和 解题思路: 因为我们很容易想到用一个max来存放找到的子序列的和中的最大值,通过不断比较,对max的值进行更新,最后我们就能够得到最大子序列的和,于是很容易想到用暴力搜索,见上一篇博客,这样的时间复杂度为O(n^3),是超时的. 又因为想到只要一个数不是负数,不管它再小,加上去也是会使和变大的,所以我们需要用另一个变量来判断即将要加上的一个

HDU 1003 Max Sum 最大连续子序列的和

Problem Description Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14. Input The first line of the input contains

最长连续公共子串、最长公共子串(可以非连续)、最长回文串(连续)、最长回文串(可以不连续)、最长递增数组的求解

问题:最长连续公共子串.最长公共子串(可以非连续).最长回文串(连续).最长回文串(可以不连续).最长递增数组.长方形镶嵌最多的求解 方法:上述问题有相似性,都可以采用动态规划进行求解. (1)最长连续公共子串: 如果A[i]==B[j], dp[i][j]=dp[i-1][j-1]+1; 否则,dp[i][j]=0; (2)最长公共子串(可非连续): 如果A[i]==B[j], dp[i][j]=dp[i-1][j-1]+1; 否则,dp[i][j]=dp[i-1][j-1]; (3)最长回文

leetcode: 2Sum/3Sum/3SumClosest/4Sum系列问题(转载)

转载:http://blog.csdn.net/li4951/article/details/8693212 leetcode上有好几道关于数组中几个数据和为target的题目.恰好正在看剑指offer中"和为s的两个数组这章",据此思想,leetcode上的三道题目都被我解决了.总结一下. 1.twoSum: 输入一个递增数组和一个数字s,在数组中查找两个数使得它们的和正好是s. 既然题目中已经提到了"递增数组",那么肯定不会暴力了.因此肯定有<O(n*n)

C++实现将十进制数转换为小于等于九的任意进制

//十进制转换为小于等于九的任意进制数 #include<iostream> #include<string> #include<stack> using namespace std; stack<int> num; void change(int N,int M) { if(N<0||M<=1) { cout<<"error!"<<endl; return; } while(N>0) { num