码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-03-28 15:37:14      阅读:127      评论:0      收藏:0      [点我收藏+]

标签:

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);
}

 

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

标签:

原文地址:http://www.cnblogs.com/wuchanming/p/4374185.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!