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

C++で順列リストから欠けている順列を見つける方法


問題概要

ある単語の順列(並べ替え)のうち、いくつかがリストとして与えられます。本来存在するはずの順列のうち、このリストに含まれていない「欠けている順列」をすべて見つけるのが本記事の目的です。

順列リスト = { "ABC", "ACB", "BAC", "BCA" } の場合、
欠けている順列は { "CAB", "CBA" } となります

アルゴリズム

  • 与えられた文字列をすべて集合(std::set)に格納する
  • 考えられるすべての順列を生成し、もう一つの集合を作る
  • 2つの集合の差分を計算して返す

C++による実装例

#include <bits/stdc++.h>
using namespace std;
void findMissingPermutation(string givenPermutation[], size_t
permutationSize) {
    vector<string> permutations;
    string input = givenPermutation[0];
    permutations.push_back(input);
    while (true) {
        string p = permutations.back();
        next_permutation(p.begin(), p.end());
        if (p == permutations.front())
            break;
        permutations.push_back(p);
    }
    vector<string> missing;
    set<string> givenPermutations(givenPermutation,
    givenPermutation + permutationSize);
    set_difference(permutations.begin(), permutations.end(),
        givenPermutations.begin(),
        givenPermutations.end(),
        back_inserter(missing));
    cout << "Missing permutations are" << endl;
    for (auto i = missing.begin(); i != missing.end(); ++i)
        cout << *i << endl;
}
int main() {
    string givenPermutation[] = {"ABC", "ACB", "BAC", "BCA"};
    size_t permutationSize = sizeof(givenPermutation) / sizeof(*givenPermutation);
    findMissingPermutation(givenPermutation, permutationSize);
    return 0;
}

上記のプログラムをコンパイルして実行すると、以下の出力が得られます。

出力

Missing permutations are
CAB
CBA

コードの解説

findMissingPermutation 関数では、まず入力配列の先頭要素を基準にして std::next_permutation を繰り返し呼び出すことで、その文字列から作れるすべての順列を辞書順に生成しています。生成された順列が先頭の文字列に戻った時点でループを終了します。なお、この方法が正しく機能するためには、初期文字列が昇順にソートされている必要がある点に注意してください。

次に、与えられた順列を std::set に格納し、std::set_difference を使って「全順列の集合」から「与えられた順列の集合」を引いた差分、すなわち欠けている順列だけを抽出して出力します。

この手法の計算量は、順列の総数が n!(n は文字数)に比例するため、文字数が増えると急激に大きくなります。長い文字列を扱う場合は、各文字の出現回数を集計して比較するなど、より効率的なアプローチを検討するとよいでしょう。

  1. C++でリンクリストをフラット化する方法【ソート済みリストの統合】

    この問題では、right と down という2つのポインタを持つノードで構成されるリンクリストが与えられます。 rightポインタ: メインとなるリンクリストをつなぐためのポインタです。 downポインタ: そのノードから始まるサブリンクリストをつなぐためのポインタです。 すべてのリンクリストはそれぞれソート済みであるものとします。求められているのは、これらの複数のリンクリストを1本のリストにまとめる(フラット化する)プログラムを作成することです。そして、結果として得られるリストもソート済みの状態になっていなければなりません。 問題の例 入力: 出力: 1-> 9->

  2. C++のstd::list::sort()でリストをソートする方法

    C++標準ライブラリによるソートの概要この記事では、C++の標準ライブラリを活用して配列や連結リスト(リンクリスト)をソートする方法について解説します。C++にはさまざまな用途に対応する多数のライブラリが標準で用意されており、ソート機能もその一つです。std::list::sort()は、リストの要素を昇順に並べ替えるメンバ関数です。この関数は安定ソート(stable sort)であるため、値が等しい要素同士の相対的な順序は保持されます。要素の比較には、デフォルトでoperator<が使用されます。サンプルコード#include <iostream> #include <li