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

C++で配列内の反転数(Inversion Count)を求めるプログラムの解説

「反転数(Inversion Count)」とは、配列を昇順にソートされた状態にするために必要な要素の入れ替え回数を表す指標です。配列がすでにソートされている場合、反転数は 0 となり、逆に配列が完全に逆順に並んでいる場合、反転数は最大値になります。

この記事では、配列内の反転数を数えるC++プログラムを実際に作成しながら、その考え方と実装方法をわかりやすく解説します。

反転数とは

配列内の2つの要素 a[i] と a[j] について、i < j かつ a[i] > a[j] が成り立つとき、このペアを「反転(inversion)」と呼びます。配列全体に存在する反転ペアの総数が反転数です。反転数が多いほど、配列はソートされた状態から遠いことになります。

アルゴリズム

ここでは最もシンプルな全ペア比較による方法(ブルートフォース)を用います。計算量は O(n²) ですが、アルゴリズムの理解には最適です。

Begin
    関数 CountInversionArray の引数:a[](配列)、n(要素数)
    カウンタ c := 0 で初期化
    i を 0 から n-1 まで繰り返す:
        j を i+1 から n-1 まで繰り返す:
            もし a[i] > a[j] ならば
                c を 1 増やす
            j ループ終了
        i ループ終了
End.

サンプルコード

以下は、ユーザーから配列の要素を入力してもらい、反転数を出力する完全なC++プログラムです。

#include<iostream>
using namespace std;
int CountInversionArray(int a[], int n) {
    int i, j, c = 0;
    for(i = 0; i < n; i++) {
        for(j = i+1; j < n; j++)
            if(a[i] > a[j])
                c++;
    }
    return c;
}
int main() {
    int n, i;
    cout<<"\n要素数を入力してください: ";
    cin>>n;
    int a[n];
    for(i = 0; i < n; i++) {
        cout<<"要素 "<<i+1<<" を入力: ";
        cin>>a[i];
    }
    cout<<"\n配列内の反転数: "<<CountInversionArray(a, n);
    return 0;
}

実行結果

入力例として、5つの要素 {3, 2, 7, 6, 1} を与えた場合の実行結果は以下の通りです。

要素数を入力してください: 5
要素 1 を入力: 3
要素 2 を入力: 2
要素 3 を入力: 7
要素 4 を入力: 6
要素 5 を入力: 1

配列内の反転数: 6

処理の流れを確認

配列 {3, 2, 7, 6, 1} における反転ペアは次の6つです。

  • (3, 2)
  • (3, 1)
  • (7, 6)
  • (7, 1)
  • (6, 1)
  • (2, 1)

したがって、出力される反転数は 6 となります。

計算量と改善のポイント

上記のプログラムは二重ループを使用しているため、時間計算量は O(n²) です。要素数が多い場合は効率が悪くなります。より高速に反転数を求めたい場合は、マージソートを応用した O(n log n) のアルゴリズムや、Binary Indexed Tree(BIT)を使った手法が知られています。まずは本記事のシンプルな実装で基本概念をしっかり理解することをおすすめします。

  1. 配列の全要素を乗算するC++プログラムの解説

    整数型の要素を持つ配列が与えられたとき、配列内のすべての要素を掛け合わせ、その積を表示することを考えます。本記事では、この問題をC++(C言語スタイルのコード)で解く方法を、アプローチ、アルゴリズム、サンプルコード、実行結果まで順を追って解説します。 例 入力: arr[]={1,2,3,4,5,6,7} 出力: 1 x 2 x 3 x 4 x 5 x 6 x 7 = 5040 入力: arr[]={3, 4, 6, 2, 7, 8, 4} 出力: 3 x 4 x 6 x 2 x 7 x 8 x 4 = 32256 解き方のアプローチ この問題は、累積用の一時変数を用意し、配列の要素を先頭

  2. C++入門:ポインタを使って配列の要素にアクセスする方法

    ポインタとは、変数のメモリ上の位置(アドレス)を格納するための特殊な変数です。言い換えれば、ポインタは特定のメモリ位置を参照しており、そのメモリ位置に格納された値を取得することを「デリファレンス(間接参照)」と呼びます。まずは、ポインタを使用して配列の単一の要素にアクセスする基本的なプログラムを見てみましょう。例1:配列の1つの要素にアクセスする#include <iostream> using namespace std; int main() {     int arr[5] = {5, 2, 9, 4, 1};