C++で配列の合計を偶数にするための最小削除数を求める方法
問題文
N個の整数からなる配列 arr[] が与えられたとします。残りの要素の合計が偶数となるようにするために、配列から取り除くべき要素の最小個数を求めるプログラムを作成します。
例
入力配列が {10, 20, 30, 5} の場合、配列全体の合計は65(奇数)です。この合計を偶数にするには、要素「5」を1つ取り除くだけで十分で、その結果 合計は60(偶数)になります。したがって、答えは「1」となります。
アルゴリズム
この問題は、偶数と奇数の加法における基本的な性質を利用することで、非常にシンプルに解くことができます。
- 偶数をいくつ足し合わせても、合計は常に偶数になります。
- 奇数を奇数個足し合わせると、合計は常に奇数になります。
- 奇数を偶数個足し合わせると、合計は常に偶数になります。
- そこで、配列内の奇数の個数をカウントします。奇数の個数が偶数であれば、どの要素も取り除く必要はありません。逆に、奇数の個数が奇数であれば、奇数の要素を任意に1つ取り除くだけで合計を偶数にできます。
つまり、答えは常に「0」または「1」のいずれかになります。
実装例(C++)
#include <bits/stdc++.h>
using namespace std;
int getMinRemovals(int *arr, int n) {
int cnt = 0;
for (int i = 0; i < n; ++i) {
if (arr[i] % 2 == 1) {
++cnt;
}
}
return (cnt % 2 == 0) ? 0 : 1;
}
int main() {
int arr[] = {10, 20, 30, 5};
int n = sizeof(arr) / sizeof(arr[0]);
cout << "Minimum required removals = " << getMinRemovals(arr, n) << endl;
return 0;
}上記のプログラムをコンパイルして実行すると、以下の出力が得られます。
出力
Minimum required removals = 1
計算量について
このアルゴリズムは配列を一度走査するだけなので、時間計算量は O(n)、追加のメモリ使用量は O(1) となり、非常に効率的です。
-
【C++】配列を互いに素な配列に変換するための最小挿入回数を求める方法
問題の概要 今回は、与えられた配列を互いに素な配列(コプライム配列)に変換するために必要な最小の挿入回数を求める、興味深い問題を取り上げます。互いに素な配列とは、隣り合う任意の2つの要素の最大公約数(GCD)が必ず1になる配列のことです。この記事では、必要な挿入回数に加えて、変換後の配列そのものも出力します。 例として、{5, 10, 20} という配列を考えてみましょう。この配列は隣接要素同士のGCDが5や10となるため、互いに素な配列ではありません。しかし、5と10の間、そして10と20の間にそれぞれ「1」を挿入すれば、{5, 1, 10, 1, 20} となり、すべての隣接ペアのGCD
-
C++で配列の合計を偶数にするために追加する最小の数を求める方法
ある数値が格納された配列があるとします。この配列の要素の合計を偶数にするために、最小でいくつの数を追加する必要があるかを求めるのが本記事の目的です。ただし、追加する数は0より大きい正の整数でなければなりません。ルールはシンプルです。要素の合計が奇数の場合は1を追加すれば偶数になります。一方、合計がすでに偶数である場合は、0を追加することが許されていないため、最小の正の偶数である2を追加することになります。アルゴリズムaddMinNumber(arr)begin s := 0 for each element e from arr, do s := e + s