LeetCode-1191 K 次串聯後最大子數組之和

題目描述:

給你一個整數數組 arr 和一個整數 k

首先,我們要對該數組進行修改,即把原數組 arr 重複 k 次。

舉個例子,如果 arr = [1, 2] 且 k = 3,那麼修改後的數組就是 [1, 2, 1, 2, 1, 2]

然後,請你返回修改後的數組中的最大的子數組之和。

注意,子數組長度可以是 0,在這種情況下它的總和也是 0

由於 結果可能會很大,所以需要 模(mod) 10^9 + 7 後再返回。 

示例 1:

輸入:arr = [1,2], k = 3
輸出:9

示例 2:

輸入:arr = [1,-2,1], k = 5
輸出:2

示例 3:

輸入:arr = [-1,-2], k = 7
輸出:0

提示:

  • 1 <= arr.length <= 10^5
  • 1 <= k <= 10^5
  • -10^4 <= arr[i] <= 10^4

題目大意:

將原來的數組擴大爲原來的k倍形成一個新的數組,問新數組的最大字段和。

思路:

此題很容易讓人想到暴力,先形成新數組再對新數組調用最大字段和算法,其實複雜度還可以往下降,看到這道題我就想起了2019ACM山東省賽的C題名字貌似是Wandering Robot,這道題給我的感覺跟那道題很相似,都是分析一下“頭”,分析一下“尾”,中間過程不用詳細考究

對於這道題來說,上來先看一下原數組所有元素之和是否大於0。

如果大於0直觀上則代表着k越大最後的字段和就越大,每一個週期都是可以使子段和增加的。此時最終的最大字段和就是中間k-2個週期的和,再加上第一個週期的尾和最後一個週期的頭(前提是加上要使結果更大);

如果小於0則直觀上則代表着k越大最後的子段和就越小,這個時候可以計算兩個週期的最大字段和(前提是k>=2),之所以計算兩個週期的,是因爲一個週期不足以代表最後的最大字段和。舉個例子,原數組爲{3,6,-50,-30,-20,1,5},原數組的最大子段和是3+6=9,而兩個週期合併後的數組爲{3,6,-50,-30,-20,1,5,3,6,-50,-30,-20,1,5},最大子段和爲1+5+3+6=15。

如果k=1即只有一個週期,直接返回原數組的最大子段和即可

上AC代碼:

class Solution {
public:
    int dp[200000];
    int kConcatenationMaxSum(vector<int>& arr, int k) {
        int len=arr.size();
        int num=0;
        int i;
        int ans=-0x3f3f3f3f;
        memset(dp,0,sizeof(dp));
        for(i=0;i<len;i++)
        {
            if(i>0&&dp[i-1]>0)
            {
                dp[i]=max(dp[i-1]+arr[i],dp[i]);
            }
            else
            {
                dp[i]=max(dp[i],arr[i]);
            }
            if(dp[i]>ans)
            {
                ans=dp[i];
            }
            num+=arr[i];
        }
        if(k>1&&num>0)
        {
            int sum1=0;
            int ans1=0;
            int sum2=0;
            int ans2=0;
            for(i=len-1;i>=0;i--)
            {
                sum1+=arr[i];
                if(sum1>ans1)
                {
                    ans1=sum1;
                }
            }
            for(i=0;i<len;i++)
            {
                sum2+=arr[i];
                if(sum2>ans2)
                {
                    ans2=sum2;
                }
            }
            long long int res=(long long int)num*(k-2)+ans1+ans2;
            return res%(1000000007);
        }
        else if(k>1)
        {
            for(i=len;i<2*len;i++)
            {
                arr.push_back(arr[i-len]);
                if(i>0&&dp[i-1]>0)
                {
                    dp[i]=max(dp[i-1]+arr[i],dp[i]);
                }
                else
                {
                    dp[i]=max(dp[i],arr[i]);
                }
                if(dp[i]>ans)
                {
                    ans=dp[i];
                }
            }
            return ans;
        }
        else
        {
            return ans;
        }
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章