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

C++で解く:すべての桁が一意(重複なし)となる、n未満の最大の数を出力するアルゴリズム

問題概要

この問題では、整数 n が与えられます。求めるのは、「n より厳密に小さい数のうち、すべての桁が互いに異なる(重複がない)最大の数」です。

具体例を使って問題を理解しましょう。

入力: n = 2332
出力: 2319

2332 未満の数の中で、桁の重複がない最大の数は 2319 となります。

解法のアプローチ

この問題は、以下のようなシンプルな戦略で解くことができます。

  1. n − 1 から 0 へ逆順にカウントダウンしていきます。
  2. 各数値について各桁の出現回数を記録し、すべての桁が一度しか現れていないかどうかを判定します。
  3. 条件を満たす数値が見つかった時点でそれを出力してループを終了します。
  4. 条件を満たさなければ、次の数値の判定へと進みます。

答えとなる数は必ず n 未満の範囲に存在するため、ループの最大実行回数は常に n 回未満に収まります。

C++による実装例

上記の解法を実装したプログラムが以下です。

#include <bits/stdc++.h>
using namespace std;
int findDistinctDigitNumber(int n) {
    for (int i = n - 1; i>=0 ; i--) {
        int count[10] = { 0 };
        int x = i;
        int count1 = 0, count2 = 0;
        while (x) {
            count[x % 10]++;
            x /= 10;
            count1++;
        }
        for (int j = 0; j < 10; j++) {
            if (count[j] == 1)
                count2++;
        }
        if (count1 == count2)
        return i;
    }
}
int main() {
    int n = 44324;
    cout<<"Number less than "<<n<<" with all digits distinct are : "<<findDistinctDigitNumber(n);
    return 0;
}

コードのポイント

  • count[10] 配列で、各桁(0〜9)の出現回数をカウントします。
  • count1 は総桁数、count2 は「ちょうど1回だけ現れた桁」の種類数です。
  • count1 == count2 が成立するとき、その数はすべての桁が一意であることを意味します。

実行結果

Number less than 44324 with all digits distinct are : 43987

このように、44324 未満で桁の重複がない最大の数として 43987 が出力されます。

計算量について

最悪の場合、答えが見つかるまで O(n × d) の時間がかかる可能性があります(d は桁数)。ただし実際には、桁が重複しない数は比較的密に存在するため、多くの場合はごく短い探索で答えが見つかります。

  1. C++で最小ヒープから値x未満のすべてのノードを出力する方法

    この問題では、最小ヒープ(Min Heap)と値xが与えられ、xより小さい値を持つすべてのノードを出力することが求められます。最小ヒープとは、すべての親ノードがその子ノードの値以下となる特殊な二分木です。この性質により、根(ルート)には常にヒープ内の最小値が格納されます。具体例を使って問題を理解しましょう。X = 45出力 − 2 4 7 10 17 22 33 34この問題を解くには、最小ヒープ全体を先行順トラバーサル(前順走査)で探索し、与えられた値xより小さい値を持つノードのみを出力します。アルゴリズムのポイント最小ヒープでは親ノードの値が必ず子ノード以下であるため、あるノードの値がx以

  2. C++ですべての要素を割り切れる配列の要素を見つける方法

    いくつかの要素を持つ配列 A があるとします。この中から「他のすべての要素を割り切ることができる」1つの要素を見つけたいと思います。例として、配列 A = [15, 21, 69, 33, 3, 72, 81] を考えてみましょう。この場合、答えは 3 になります。リスト内のすべての数値が3で割り切れるためです。解決策のアプローチこの問題は、以下の手順でシンプルに解くことができます。まず、配列内の最小値を求めます。次に、すべての要素がその最小値で割り切れるかどうかを確認します。すべて割り切れれば、その最小値を返します。1つでも割り切れない要素があれば、-1 を返します(条件を満たす要素は存在し