C++の部分配列動的プログラミングの問題

1. 最大サブアレイと   バックル

整数の配列を指定してnums、最大合計を持つ連続部分配列 (部分配列には少なくとも 1 つの要素が含まれます) を見つけて、その最大合計を返します。

サブ配列は配列の連続した部分です。

例 1:

入力: nums = [-2,1,-3,4,-1,2,1,-5,4]
出力: 6
説明:連続する部分配列の合計 [4,-1,2,1] が最大です、6です。

例 2:

入力: nums = [1]
出力: 1

例 3:

入力: nums = [5,4,-1,7,8]
出力: 23
class Solution {
    const int INF=0x3f3f3f3f;
public:
    int maxSubArray(vector<int>& nums) 
    {
        int n=nums.size();
        vector<int> dp(n+1);
        int ret=-INF;
        for(int i=1;i<=n;i++)
        {
            dp[i]=max(nums[i-1],dp[i-1]+nums[i-1]);
            ret=max(ret,dp[i]);//不能从dp[0]开始找,从dp[1]开始找
        }
        
        return ret;
    }
};

2. 最大の円形サブアレイと世界のオタクに愛される技術成長プラットフォーム LeetCode の公式ウェブサイト

n長さの整数の循環配列 を指定するとnums 、 の空でない部分配列の最大の合計 を返します。 nums

円形配列は 、配列の終端がリングの先頭に接続されることを意味します。正式には、nums[i]の次の要素は でnums[(i + 1) % n]nums[i] 前の要素は ですnums[(i - 1 + n) % n]

サブ配列には、nums 固定バッファー内の各要素を最大 1 回だけ含めることができます 。正式には、部分配列 の場合 nums[i], nums[i + 1], ..., nums[j] 、 i <= k1, k2 <= j 内に は存在しませんk1 % n == k2 % n 。

例 1:

入力: nums = [1,-2,3,-2]
出力: 3
説明:部分配列 [3] から最大和 3 を取得します。

例 2:

入力: nums = [5,-3,5]
出力: 10
説明:部分配列 [5,5] から最大合計を取得します 5 + 5 = 10

例 3:

入力: nums = [3,-2,2,-3]
出力: 3
説明:部分配列 [3] と [3,-2,2] の両方から 3 の最大和を取得できます。
class Solution {
    const int INF = 0x3f3f3f3f;
public:
    int maxSubarraySumCircular(vector<int>& nums)
    {
        int n = nums.size();
        int sum = 0;
        for (auto sh : nums) sum += sh;
        vector<int> f(n + 1);//找最大值
        vector<int> g(n + 1);//找最小值

        int retmax = -INF;
        int retmin = INF;

        for (int i = 1; i <= n; i++)
        {
            f[i] = max(nums[i - 1], f[i - 1] + nums[i - 1]);
            retmax = max(retmax, f[i]);

            g[i] = min(nums[i - 1], g[i - 1] + nums[i - 1]);
            retmin = min(retmin, g[i]);
        }
        
        /*if(sum-retmin==0)
            return retmax;
        return retmax == retmin ? retmax : max(retmax, sum - retmin);*/
        return retmax == retmin ? retmax : max(retmax, sum - retmin==0?retmax:sum-retmin);   
    }
};

3. 最大のサブ製品ラインナップLeetCode 公式ウェブサイト - 世界中のオタクに愛されるテクノロジー成長プラットフォーム

integer の配列が与えられた場合nums 、配列内で最大の積を持つ空でない連続部分配列 (部分配列には少なくとも 1 つの数値が含まれます) を見つけて、その部分配列に対応する積を返してください。

テスト ケースの答えは 32 ビット整数です。

サブ配列は、配列の連続したサブシーケンスです。

例 1:

入力: nums = [2,3,-2,4]
出力: 6
説明: サブ配列 [2,3] には最大の積 6 があります。

例 2:

入力: nums = [-2,0,-1]
出力: 0
説明:  [-2,-1] は部分配列ではないため、結果が 2 になることはありません。
class Solution {
public:
    int maxProduct(vector<int>& nums)
    {
        int n=nums.size();
        vector<int> f(n+1);
        auto g=f;
        int ret=INT_MIN;
        int retmin=INT_MAX;

        f[0]=g[0]=1;
        

        for(int i=1;i<=n;i++)
        {
            f[i]=max(nums[i-1],max(f[i-1]*nums[i-1],g[i-1]*nums[i-1]));
            ret=max(ret,f[i]);//不能从dp[0]开始找,从dp[1]开始找
            g[i]=min(nums[i-1],min(g[i-1]*nums[i-1],f[i-1]*nums[i-1]));
            retmin=min(retmin,g[i]);
        }
        
        return ret;
    }
};

4. 正のスコアを持つ最長部分配列の長さ  LeetCode 公式ウェブサイト - 世界のオタクに愛される技術成長プラットフォーム

整数の配列が与えられた場合nums 、その積が正の数になる最長の部分配列の長さを見つけてください。

配列の部分配列は、元の配列内の 0 個以上の連続する数値の配列です。

積が正の数になる最長の部分配列の長さを返してください。

例 1:

入力: nums = [1,-2,-3,4]
出力: 4
説明:配列自体の積は、値が 24 の正の数です。

例 2:

入力: nums = [0,1,-2,-3,-4]
出力: 3
説明:最長の正の積を持つ部分配列は [1,-2,-3] で、積は 6 です。
積は正の数ではない 0 になるため、部分配列に 0 を含めることもできないことに注意してください。

例 3:

入力: nums = [-1,-2,-3,0,1]
出力: 2
説明:積が正の数になる最長の部分配列は、[-1,-2] または [-2,-3] です。 
class Solution {
public:
    int getMaxLen(vector<int>& nums) 
    {
        int n=nums.size();
        vector<int> f(n+1);
        auto g=f;
    
        int ret=INT_MIN;
        for(int i=1;i<=n;i++)
        {
            if(nums[i-1]>0)//正数
            {
                f[i]=f[i-1]+1;
                g[i]=g[i-1]==0?0:g[i-1]+1;
            }
            else if(nums[i-1]<0)//负数
            {
                f[i]=g[i-1]==0?0:g[i-1]+1;
                g[i]=f[i-1]+1;
            }
            ret=max(ret,f[i]);
        }
        return ret;
    }
};

5. LeetCode  公式ウェブサイト - 世界中のオタクに愛されるテクノロジー成長プラットフォーム

シーケンスに少なくとも 3 つの要素があり、隣接する 2 つの要素の差が同じである場合、そのシーケンスは算術シーケンスであると言われます。

  • たとえば、[1,3,5,7,9]、 、[7,7,7,7][3,-1,-5,-9]等差数列です。

整数の配列を指定するとnumsnums配列内の算術配列であるサブ配列の数を返します。

サブ配列は、配列内の連続したシーケンスです。

例 1:

入力: nums = [1,2,3,4]
出力: 3
説明: nums には 3 つのサブ配列があります: [1, 2, 3]、[2, 3, 4]、および [1,2,3,4 ]自体。

例 2:

入力: nums = [1]
出力: 0
class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& nums) 
    {
        int n=nums.size();
        int dp[2]={0};
        int sum=0;
        for(int i=2;i<n;i++)
        {
            
            dp[i%2]=nums[i]-nums[i-1]==nums[i-1]-nums[i-2]?dp[(i-1)%2]+1:0;
            
            sum+=dp[i%2];
        }
        return sum;
    }
};

6. 最長の乱流部分配列  LeetCode 公式ウェブサイト - 世界のオタクに愛される技術成長プラットフォーム

整数配列を指定するとarr 、最大の乱流部分arr配列 の 長さを返します。 

部分配列内の要素の隣接する各ペア間で比較符号が反転している場合、その部分配列は 乱流部分配列です 。

より正式には、arr の部分配列が 次の条件のみを満たす場合、乱流部分配列A[i], A[i+1], ..., A[j] と呼ばれます

  • 場合 i <= k < j :
    • k 奇数の 場合A[k] > A[k+1]、、、
    • kが偶数の場合、 A[k] < A[k+1];
  • または次の場合 i <= k < j :
    • kが偶数の場合、 A[k] > A[k+1] 、および
    • k 奇数の 場合はA[k] < A[k+1].

例 1:

入力: arr = [9,4,2,10,7,8,8,1,9]
出力: 5
説明: arr[1] > arr[2] < arr[3] > arr[4] < arr[ 5]

例 2:

入力: arr = [4,8,12,16]
出力: 2

例 3:

入力: arr = [100]
出力: 1
class Solution {
public:
    int maxTurbulenceSize(vector<int>& arr) 
    {
        int n=arr.size();
        vector<int> f(n,1);
        auto g=f;
        int ret=1;
        for(int i=1;i<n;i++)
        {
            if(arr[i]>arr[i-1])
            {
                f[i]=g[i-1]+1;
            }
            else if(arr[i]<arr[i-1])
            {
                g[i]=f[i-1]+1;
            }
            ret=max(ret,max(g[i],f[i]));
        }
        return ret;
    }
};

Guess you like

Origin blog.csdn.net/weixin_66828150/article/details/132100499