C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++で最大1要素を削除した後の部分配列の最大和を最大化する方法

問題文

N個の整数からなる配列 arr[] が与えられます。まず最大部分配列和を求め、その部分配列から最大で1つの要素を削除したとき、合計が最大になるようにします。つまり、削除できる要素は最大で1つまでとし、削除後の合計を最大化することがこの問題の目的です。

例として、入力配列が {1, 2, 3, -2, 3} の場合を考えてみましょう。この配列の最大部分配列は配列全体 {1, 2, 3, -2, 3} で、その和は7です。ここで -2 を削除すると、残りの配列は次のようになります。

{1, 2, 3, 3} となり、和は9でこれが最大となります。

アルゴリズム

この問題は、カダネのアルゴリズム(Kadane's algorithm)を応用することで効率的に解くことができます。

  1. まず、カダネのアルゴリズムを使って最大部分配列和 sum を求めます。
  2. 次に、いくつかの変更を加えたカダネのアルゴリズムを再度適用します。今度は現在の部分配列内の最小要素も同時に追跡し、currentMax が sum に達した時点で、その部分配列の最小要素を記録します(部分配列の長さが1の場合は削除しないものとして0を記録)。
  3. 最終的な答えは、sum から記録した最小値を引いた値になります。

実装例

#include <bits/stdc++.h>
using namespace std;
int getMaxSubarraySum(int *arr, int n){
   int max = INT_MIN;
   int currentMax = 0;
   for (int i = 0; i < n; ++i) {
      currentMax = currentMax + arr[i];
      if (max < currentMax) {
         max = currentMax;
      }
      if (currentMax < 0) {
         currentMax = 0;
      }
   }
   return max;
}
int getMaxSum(int *arr, int n){
   int cnt = 0;
   int minVal = INT_MAX;
   int minSubarr = INT_MAX;
   int sum = getMaxSubarraySum(arr, n);
   int max = INT_MIN;
   int currentMax = 0;
   for (int i = 0; i < n; ++i) {
      currentMax = currentMax + arr[i];
      ++cnt;
      minSubarr = min(arr[i], minSubarr);
      if (sum == currentMax) {
         if (cnt == 1) {
            minVal = min(minVal, 0);
         } else {
            minVal = min(minVal, minSubarr);
         }
      }
      if (currentMax < 0) {
         currentMax = 0;
         cnt = 0;
         minSubarr = INT_MAX;
      }
   }
   return sum - minVal;
}
int main(){
   int arr[] = {1, 2, 3, -2, 3};
   int n = sizeof(arr) / sizeof(arr[0]);
   cout << "Maximum sum = " << getMaxSum(arr, n) << endl;
   return 0;
}

出力

上記のプログラムをコンパイルして実行すると、次の出力が得られます。

Maximum sum = 9
  1. C++で最大2つの要素の符号を反転した後の最大部分配列和を求める方法

    問題概要この記事では、配列が与えられたときに「最大2つの要素の符号を反転する」操作を行った後の、最大部分配列和(サブアレイ合計)を求めるC++プログラムを紹介します。つまり、配列内の任意の要素を最大2つまで選んで符号を反転し、その状態で合計値が最大になる部分配列(連続する要素の並び)を見つけることが目的です。入力例と出力例入力:array = {-5, 1, 3, 8, -2, 4, 7}出力:30解説:インデックス0から6までのすべての要素を対象に、負の値である -5 と -2 の符号を反転します。元の配列の合計は16ですが、-5→5、-2→2 と反転すると 5+1+3+8+2+4+7 =

  2. 【C++】K回の符号反転操作で配列の合計を最大化する方法

    問題の概要サイズ n の整数型配列と、操作回数を表す数値 k が与えられます。私たちの課題は、この配列に対してちょうど k 回の「修正操作」を実行することです。ここでいう修正操作とは、1 回ごとに配列内の任意の要素 arr[i] を選び、その符号を反転させる(すなわち arr[i] = -arr[i] とする)ことを指します。k 回の操作を終えた時点で、配列全体の合計値が最大になるように操作を行うことが目標です。例として、入力が arr[] = {7, -3, 5, 4, -1} の場合、最大合計は 20 になります。具体的な手順は以下のとおりです。まず -3 を反転します。配列は {7, 3