C++で配列の数字から作れる最大の数を求める方法
数字の配列が与えられたとき、その配列に含まれるすべての数字を使って作れる最大の数を求める問題を考えてみましょう。
例えば、配列が [3, 3, 9, 6, 2, 5] の場合、これらの数字を組み合わせて作れる最大の数は 965332 になります。
アプローチの考え方
この問題に対する最も直感的な解法は、配列内の数字を降順(非増加順)にソートして、その順に出力することです。ソートを使えば確かに正しい答えが得られますが、計算量は O(n log n) となります。
しかし、より効率的な方法があります。それがカウントソート(頻度カウント)の考え方を応用する手法です。
具体的には、次の手順で処理を行います。
- サイズ10の配列を作成し、各数字(0〜9)の出現回数を記録します。
- 9から0に向かって順番に、記録された回数だけ数字を出力していきます。
この方法なら O(n + k)(kは数字の種類数)で処理でき、ソートよりも高速に動作します。
サンプルコード
#include <iostream>
#include <string>
using namespace std;
int maxNumFromNum(int arr[], int n) {
int freq[10] = {0};
for (int i=0; i<n; i++)
freq[arr[i]]++;
int res = 0, mul = 1;
for (int i = 0; i <= 9; i++) {
while (freq[i] > 0) {
res = res + (i * mul);
freq[i]--;
mul = mul * 10;
}
}
return res;
}
int main() {
int digits[] = {3, 3, 9, 6, 2, 5};
int n = sizeof(digits)/sizeof(digits[0]);
cout << "Maximum number: " << maxNumFromNum(digits, n);
}
実行結果
Maximum number: 965332
コードの解説
このプログラムのポイントは以下の通りです。
- freq 配列: 各数字の出現回数を格納します。例えば入力に「3」が2つ含まれていれば、freq[3] は 2 になります。
- res と mul: 結果の数値を組み立てるために使用します。mul を10倍ずつ増やしながら、大きい数字から順に上位の桁へ配置していきます。
- ループの順序: 9から0へ向かって処理することで、大きな数字が自然と左側(上位の桁)に配置され、最大の数が完成します。
なお、結果を整数型(int)で返しているため、桁数が非常に多い場合はオーバーフローに注意が必要です。そのようなケースでは long long 型や文字列として扱う方法を検討するとよいでしょう。
-
C++で指定された差分を持つペアを見つける方法
はじめに 配列 A に n 個の異なる要素が格納されているとします。この配列から、2つの要素 x と y の差が指定された値 d と一致するようなペア (x, y) をすべて見つける必要があります。 例として、配列が A = [10, 15, 26, 30, 40, 70]、指定された差分が 30 である場合を考えます。このとき、該当するペアは (10, 40) と (40, 70) です。 解法:ツーポインタ法 この問題は、配列が昇順にソートされていることを前提とすれば、ツーポインタ(二重インデックス)法を使って効率的に解くことができます。まず、1つ目のポインタ「i」を先頭の要素に、2つ目の
-
C++で「x + 桁の合計 = n」を満たす数xを見つける方法
この記事では、ある整数 n が与えられたとき、「x + x の各桁の合計 = n」という条件を満たす数 x を求める問題を解説します。例として、n = 21 の場合を考えてみましょう。このとき答えは x = 15 となります。なぜなら、15 の各桁の合計は 1 + 5 = 6 であり、15 + 6 = 21 となって、与えられた n と一致するからです。解き方のアプローチこの問題はシンプルな方法で解くことができます。1 から n まで順番に数を調べていき、それぞれの数について「その数自身 + 各桁の合計」が n と等しくなるかどうかを確認します。条件を満たす数が見つかった時点で処理を終了し、そ