小于等于给定值的最长子数组

  求数组中等于给定值的最长子数组

//数组中等于给定值的最长子数组
#include <iostream>
#include <map>
#include <vector>
using namespace std;

int longest_sum_sub(const vector<int> &a,const int &aim)
{
    if(a.empty()||a.size()==0)
        return -1;
        
    map<int,int> map;//sum,pos;
    map.insert({0,-1});
    int maxLen=0;
    int curSum=0;
    for(int i=0;i<a.size();++i)
    {
        curSum+=a[i];
        if(map.find(curSum-aim)!=map.end())
            maxLen=max(maxLen,i-map.find(curSum-aim)->second);
        if(map.count(curSum)==0)
            map.insert({curSum,i});
    }
    return maxLen;
}

int main()
{
    vector<int> a{6,1,3,2,-1,1,5};
    cout<<longest_sum_sub(a,6)<<endl;
    return 0;
}

拓展一

  一个数组中既有奇数又有偶数,求奇数和偶数个数相等的最长的子数组

  将奇数记为-1,偶数记为1,题目转换为求数组中等于0的最长子数组

//一个数组中既有奇数又有偶数,求奇数和偶数个数相等的最长的子数组
#include <iostream>
#include <map>
#include <vector>
using namespace std;

int odd_and_even_equal_num(const vector<int> &a)
{
    if(a.empty()||a.size()==0)
        return -1;
        
    int curSum=0;
    int maxLen=0;
    map<int,int> map;
    map.insert({0,-1});
    vector<int> temp(a.begin(),a.end());
    for(int i=0;i<temp.size();++i)
    {
        if((temp[i]&1)==1)
            temp[i]=-1;
        else
            temp[i]=1;
    }

    for(int i=0;i<temp.size();++i)
    {
        curSum+=temp.at(i);
        if(map.count(curSum)!=0)
            maxLen=max(maxLen,i-map.find(curSum)->second);
    
        if(map.count(curSum)==0) 
            map.insert({curSum,i});
    }
    return maxLen;
}
int main()
{
    vector<int> a{6,8,2,6};
    cout<<odd_and_even_equal_num(a)<<endl;
    return 0;
}

 拓展二

#include <iostream>
#include <vector>
using namespace std;

//都是正数的数组中,小于等于给定值的子数组的最大长度
int max_len(const vector<int> &a,const int &aim)
{
    if(a.empty()||a.size()<0)
        return -1;
    int L=0,R=0;
    int len=0;
    int sum=a.at(0);
    while(R<a.size())
    {
        if(sum==aim)
        {
            len=max(len,R-L+1);
            sum-=a.at(L++);
        }
        else if(sum<aim)
        {
            ++R;
            if(R>=a.size())
                break;
            sum+=a.at(R);
        }
        else
            sum-=a.at(L++);
    }
    return len;
}
//有正有负的数组中,小于等于给定值的最大子数组长度
int max_len_pro(const vector<int>& a, const int& aim)
{
    if(a.empty()||a.size()<0)
        return -1;
    vector<int> sums(a.size(),0);//从后向前计算,最小累加和数组
    vector<int> ends(a.size(),0);//与sums对应的最小累加和的右边界的下标
    sums.at(a.size()-1)=a.at(a.size()-1);
    ends.at(a.size()-1)=a.size()-1;

    //生成sums和ends数组信息
    for(int i=a.size()-2;i>=0;--i)
    {
        if(sums.at(i+1)<0)
        {
            sums.at(i)=a.at(i)+sums.at(i+1);
            ends.at(i)=ends.at(i+1);
        }
        else
        {
            sums.at(i)=a.at(i);
            ends.at(i)=i;
        }
    }

    int R=0;//下一个即将要算进来的块的开头
    int sum=0;
    int res_len=0;
    for(int i=0;i<a.size();++i)
    {
        while(R<a.size()&&sum+sums.at(R)<=aim)
        {
            sum+=sums.at(R);
            R=ends.at(R)+1;//下一个带扩的位置
        }
        //向右扩不动
        sum-=R>i?a.at(i):0;
        res_len=max(res_len,R-i);
        R=max(R,i+1);
    }
    return res_len;
}

int main()
{
    vector<int> a{1,2,3,6,2,4};
    cout<<max_len(a,6)<<endl;
    cout<<max_len_pro(a,6)<<endl;
    return 0;
}

 

posted on 2019-03-18 22:45  tianzeng  阅读(262)  评论(0编辑  收藏  举报

导航