Leetcode 陣列中和為給定值的最長子陣列

一隻老風鈴發表於2020-10-29

題目描述

給定一個陣列arr,該陣列無序,但每個值均為正數,再給定一個正數k。求arr的所有子陣列中所有元素相加和為k的最長子陣列的長度

例如,arr = [1, 2, 1, 1, 1], k = 3

累加和為3的最長子陣列為[1, 1, 1],所以結果返回3

輸入

5 3
1 2 1 1 1

輸出

3

 

 

【思路】

由於全部為正數,可以有這樣一個肯定的資訊

若當前視窗的值大於K 那麼左邊界      =》sum-=arr[left++] 因為 right++視窗增大一定更加超過K

若當前視窗的值等於K 那麼更新邊界    =》sum-=arr[left++]  因為right++一定超過K

若當前視窗的值小於K  那麼更新右邊界  =》sum+=arr[++right] 因為left++一定更小

總結而言

對於可以使用滑動視窗的問題其特點是:在當前視窗情況下,下一步視窗的移動(邊界變化)是確定的

 

int main()
{
    int N,K;
    cin>>N>>K;
    vector<int> add(N,0);
    for(int i=0;i<N;i++)
        cin>>add[i];
    int l=0;
    int r=0;
    int sum=add[l];  //初始化滑動視窗的值
    int ans=0;
    while(r<N)
    {
        if(sum==K)
        {
            ans=max(ans,r-l+1);
            sum-=add[l++];
        }
        else if(sum<K)
        {
            sum+=add[++r];  //先r++ 然後累加到sum
        }
        else
        {
            sum-=add[l++]; //最初的左邊界值減掉 然後l++
        }
    
    }
    cout<<ans<<endl;
 
    
}

 

【問題變形】

題目描述

給定一個無序陣列arr, 其中元素可正、可負、可0。給定一個整數k,求arr所有子陣列中累加和為k的最長子陣列長度

輸入描述:

第一行兩個整數N, k。N表示陣列長度,k的定義已在題目描述中給出
第二行N個整數表示陣列內的數

【思路】

這類問題無法使用滑動視窗,因為一個視窗的情況無法確定下一步移動情況

對於該問題的思路是:

採取map<int,int>   map[sum]=i   表示 前面i項累積和為sum  即i為累積和為sum的右邊界

那麼對於第K項:

sum+=arr[k]  如果之前map中存在 map[sum-k]  那麼這一段區間的和為K  即通過兩段前k項 相減  =》確定符合要求子區間

同時注意一點,由於需要求解最長的區間,因此map[sum]只在第一次賦值使得區間長度儘可能長

 

int N,K;
    cin>>N>>K;
    unordered_map<int,int> mp;
    mp[0]=0;
    int sum=0;
    int temp;
    int ans=0;
    for(int i=1;i<=N;i++)
    {
        cin>>temp;
        sum+=temp;
        if(mp.find(sum-K)!=mp.end())
        {
            ans=max(ans,i-mp[sum-K]);
        }
        if(mp.find(sum)==mp.end())  //總是在第一組時候插入  使得那個值儘可能早
            mp[sum]=i;
        
    }
    cout<<ans<<endl;

 

相關文章