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

指定された配列からn個の最小要素を元の順序で出力するアルゴリズム

k個の要素からなる配列が与えられたとき、プログラムはその中からn個(ここではk個)の最小要素を見つけ出し、配列に現れた元の順序のまま出力する必要があります。

例えば、入力が arr[] = {1, 2, 4, 3, 6, 7, 8} で k=3 の場合、配列の中から3つの最小要素を元の順序で、すなわち 1、次に 2、そして 3 の順に表示します。

入力 : arr[] = {1, 2, 4, 3, 6, 7, 8}, k=3
出力 : 1, 2, 3

アルゴリズム

この問題は、挿入ソートの考え方を応用することで効率よく解くことができます。基本的な発想は次のとおりです。

  • 配列の先頭k個を「暫定の最小k要素」として保持します。
  • k番目以降の要素を順に走査し、暫定のk要素の中の最大値より小さい要素が見つかったら、最大値を取り除いて新しい要素を末尾に追加します。
  • この操作を配列の最後まで繰り返すことで、先頭k個が常に「それまでに見た要素の中で最小のk個」に保たれます。

手順を擬似コードで表すと以下のようになります。

START
ステップ1 → 変数を宣言する:int i, max, pos, j, k=4、および配列サイズ size
ステップ2 → i=k から i<size まで i++ でループ
    max = arr[k-1] とする
    pos = k-1 とする
    j=k-2 から j>=0 まで j-- でループ
        もし arr[j] > max ならば
            max = arr[j] とする
            pos = j とする
        終了
    終了
    もし max > arr[i] ならば
        j = pos とする
        j < k-1 の間ループ
            arr[j] = arr[j+1] とする
            j++ とする
        終了
        arr[k-1] = arr[i] とする
    終了
終了
ステップ3 → i=0 から i<k まで i++ でループ
    arr[i] を出力する
STOP

サンプルコード(C言語)

上記のアルゴリズムをC言語で実装した例が次のコードです。

#include <stdio.h>
int main() {
    int arr[] = {5,8,3,1,2,9};
    int i, max, pos, j, k=4;
    int size = sizeof(arr)/sizeof(arr[0]);
    // 挿入ソートの考え方を使い、k番目以降の要素を処理する
    for(i=k;i<size;i++){
        max = arr[k-1];
        pos = k-1;
        for(j=k-2;j>=0;j--) {
            if(arr[j]>max) {
                max = arr[j];
                pos = j;
            }
        }
        if ( max> arr[i] ) {
            j = pos;
            while( j < k-1 ) {
                arr[j] = arr[j+1];
                j++;
            }
            arr[k-1] = arr[i];
        }
    }
    // 最初のk個の要素を出力する
    for (i = 0; i < k; i++) {
        printf("%d ", arr[i]);
    }
    return 0;
}

実行結果

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

5 3 1 2

この出力は、配列 {5, 8, 3, 1, 2, 9} の中から最小の4つの要素である 5, 3, 1, 2 が、元の配列での出現順序を保ったまま正しく出力されたことを示しています。

計算量について

外側のループは配列の残りの要素(size - k 個)を走査し、内側のループはk個の暫定要素の中から最大値を探すため、全体の時間計算量は O((size - k) × k) となります。配列の並び順を大きく変更せずに元の順序を維持できる点が、この手法の特徴です。

  1. Cプログラムで指定された配列から下三角行列パターンを出力する方法

    n×n の行列が与えられたとき、その行列を下三角行列(下三角形パターン)の形で出力するのが本記事のテーマです。下三角行列とは、主対角線より下の要素(主対角線上の要素を含む)が元の値をそのまま保持し、主対角線より上の要素がすべて 0 になった行列のことです。次の図を見ると理解しやすくなります。図の緑色の要素は主対角線より下(および主対角線上)の要素で、元の値がそのまま残ります。一方、赤色の要素は主対角線より上の要素で、すべて 0 に設定されます。入力と出力の例入力: matrix[3][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9

  2. C++プログラム:配列内の各要素の最後の出現を相対的な順序で出力する方法

    配列 a[] が与えられたとき、リスト内の各要素について最後に出現したものだけを出力するのが本記事の目的です。ここでは単純に重複要素を削除するだけでなく、各要素が配列内で最後に出現したタイミングに基づき、元の相対的な順序を維持したまま出力する必要があります。例えば、6つの要素を持つ配列 {1, 3, 2, 3, 1, 2} には重複した値が含まれています。この場合、期待される結果は「3 1 2」になります。入力例と出力例Input: a[]={4,2,2,4,1,5,1} Output : 2 4 5 1この例では、「2」はインデックス2で最後に出現し、「4」はインデックス3、「5」はインデッ