C++で配列の数字から作る2つの数値の合計を最小化する方法
問題の概要
0から9までの値を含む数字の配列が与えられます。この問題では、配列内のすべての数字を使って2つの数値を作り、その合計が最小になるようにすることが求められます。重要な制約として、与えられた配列のすべての数字を必ず使用しなければなりません。
例
入力配列が {7, 5, 1, 3, 2, 4} の場合、最小合計は 382 となります。これは、135 と 247 という2つの数値を作成できるためです(135 + 247 = 382)。
アルゴリズムの考え方
この問題は貪欲法(グリーディ法)で解くことができます。合計を最小にするには、小さい桁の数字ほど大きな位(上位の桁)に配置するのが最適だからです。手順は以下の通りです。
- 配列を昇順にソートします。
- ソート済みの配列から、偶数インデックスと奇数インデックスの数字を交互に取り出し、それぞれ別の数値を構成します。これにより、小さい数字が2つの数値の上位の桁に均等に分散されます。
C++での実装例
#include <bits/stdc++.h>
using namespace std;
int getMinSum(int *arr, int n) {
sort(arr, arr + n);
int a = 0;
int b = 0;
for (int i = 0; i < n; ++i) {
if (i % 2 == 0) {
a = a * 10 + arr[i];
} else {
b = b * 10 + arr[i];
}
}
return a + b;
}
int main() {
int arr[] = {7, 5, 1, 3, 2, 4};
int n = sizeof(arr) / sizeof(arr[0]);
cout << "Minimum sum = " << getMinSum(arr, n) << endl;
return 0;
}
上記のプログラムをコンパイルして実行すると、次の出力が得られます。
実行結果
Minimum sum = 382
計算量について
このアルゴリズムの時間計算量は、ソート処理が支配的となるため O(n log n) です。空間計算量は追加の配列を使用しないため O(1) となります。数字を交互に振り分けることで、両方の数値の桁数の差が最大1桁に抑えられ、結果として合計が最小になります。
-
C++で桁の合計に基づいて数値をソートする方法
この記事では、各数値の「桁の合計(各桁の数字を足した値)」に基づいて数値を並べ替える方法を解説します。桁の合計が小さい数値ほど先頭に配置され、合計が大きい数値ほど後ろに配置されます。ソートの例例として、次のようなデータを考えてみましょう。data = {14, 129, 501, 23, 0, 145}このデータを桁の合計順にソートすると、以下のようになります。0 → 桁の合計は 014 → 桁の合計は 1 + 4 = 523 → 桁の合計は 2 + 3 = 5501 → 桁の合計は 5 + 0 + 1 = 6145 → 桁の合計は 1 + 4 + 5 = 10129 → 桁の合計は 1 +
-
C++の配列パズル:減算演算子を使わずに「自分以外の要素の合計」を求める方法
今回は、配列に関する興味深い問題を紹介します。n個の要素を持つ配列が与えられ、それをもとに同じくn個の要素を持つ別の配列を作成します。ただし、新しい配列のi番目には、元の配列のi番目の要素を除いたすべての要素の合計を格納します。さらに重要な制約として、減算演算子(-)を使用してはいけないという条件が課されています。 問題のポイント もし減算が使えるのであれば、話は簡単です。まず全要素の合計を求めておき、そこからi番目の要素を引いた値を新しい配列のi番目に格納すればよいだけです。しかし、この問題では減算が禁止されているため、別のアプローチが必要になります。 そこで、各位置i(0〜n-1)について