C++で配列の全要素を0にするための最小操作回数を求める方法
問題の概要
サイズNの配列が与えられ、各要素は「1」または「0」のいずれかです。この課題では、すべての要素を0に変換するために必要な最小操作回数を求めます。
実行できる操作は以下のとおりです。
ある要素が「1」である場合、その値を「0」に変更できます。このとき、次のような効果が発生します。
- 隣接する次の要素が「1」であれば、その要素は自動的に「0」へ変換されます。
- 隣接する次の要素がすでに「0」であれば、何も起こりません。
例として、次の配列を考えてみましょう。
arr[] = {1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1}
この場合、すべての要素を0にするには 4回 の操作が必要ですアルゴリズム
- 現在の要素が「1」であればカウントを1増やし、次に「0」が現れる位置まで探索を進めます。連続する「1」はすべて自動的に「0」へ変換されるため、まとめて処理できるからです。
- 最終的なカウントを結果として返します。
C++による実装例
#include <iostream>
#define SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
using namespace std;
int performMinOperation(int *arr, int n){
int i, cnt = 0;
for (i = 0; i < n; ++i) {
if (arr[i] == 1) {
int j;
for (j = i + 1; j < n; ++j) {
if (arr[j] == 0) {
break;
}
}
i = j - 1;
++cnt;
}
}
return cnt;
}
int main(){
int arr[] = {1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1};
cout << "Minimum required operations = " << performMinOperation(arr, SIZE(arr)) << endl;
return 0;
}
出力結果
上記のプログラムをコンパイルして実行すると、次の出力が得られます。
Minimum required operations = 4
考え方のポイント
この問題の鍵となるのは、「連続する1のグループ数」を数えるという発想です。上記の例では、配列内に「1」が連続するブロックが {1, 1}、{1, 1, 1, 1, 1}、{1}、{1} の4つ存在します。各グループの先頭要素に対して一度だけ操作を行えば、残りの要素は連鎖的に自動的に0へ変換されます。したがって、必要な最小操作回数は「1」の連続グループの総数と一致します。
このアルゴリズムの計算量はO(N)であり、配列を一度走査するだけで答えが求まるため、非常に効率的です。
-
C++で配列の全要素を同じ値にするための最小削除操作数を求めるアルゴリズム
問題概要n個の要素からなる配列が与えられます。要素には重複が含まれる場合があります。この配列から任意の数の要素を削除できるとき、すべての要素を同じ値にするために必要な最小の削除数を求めるのが課題です。例として、次の配列を考えてみましょう。arr[] = {10, 8, 10, 7, 10, -1, -4, 12}この場合、最も多く出現している「10」以外の5つの要素を削除すれば、配列の全要素を10で統一できます。つまり、答えは5回の削除となります。解法の考え方この問題の鍵となるのは、「削除する量を最小化する = 残す要素の数を最大化する」という発想です。全要素を同じ値にするためには、必ずどれか
-
Pythonで配列の全要素を等しくするために必要な操作回数の求め方
ある要素の配列が与えられ、各ステップで n - 1 個の要素を1ずつ増やすことが許されているとします。このとき、配列の全要素を等しくするまでに必要な操作の総回数を求めるのが目標です。例えば、リスト [1, 2, 3] の場合、すべての要素を等しくするには3回の操作が必要になります。この問題に対する基本的な解法の一つは、各ステップで最大値を見つけ、それ以外の要素を1ずつ増やしていくというものです。実際にコードを書いてみましょう。方法1:シミュレーションによる解法def main(): # 配列の初期化 arr = [1, 2, 3] # 操作回数を0で初期化 no