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

【C++】整数配列から重複を除いた一意の要素を出力する3つの方法

問題概要

この記事では、整数値の配列が与えられたときに、その配列に含まれる重複しない(一意の)要素だけを出力する方法を解説します。出力には、同じ値が何度現れても1度だけ含まれるようにします。

入出力例

Input: array = {1, 5, 7, 12, 1, 6, 10, 7, 5}
Output: 1 5 7 12 6 10

上記の例では、157 がそれぞれ2回ずつ現れていますが、出力ではそれぞれ1度だけ表示されています。

方法1: 二重ループで重複をチェックする

最もシンプルなアプローチは、各要素についてそれ以前の要素と比較し、初めて登場した要素のみを出力する方法です。外側のループで各要素を取り出し、内側のループでそれより前方の要素と照合します。一致する要素が存在しなければ、その値は初登場なので出力します。

#include <iostream>
using namespace std;

void printDistinctValues(int arr[], int n) {
    for (int i = 0; i < n; i++) {
        int j;
        for (j = 0; j < i; j++)
            if (arr[i] == arr[j])
                break;
        if (i == j)
            cout << arr[i] << "\t";
    }
}

int main() {
    int arr[] = {1, 5, 7, 12, 1, 6, 10, 7, 5};
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << "Distinct values of the array are :\n";
    printDistinctValues(arr, n);
    return 0;
}

実行結果

Distinct elements of the array are −
1 5 7 12 6 10

この方法は実装が非常に簡単ですが、二重ループを使用するため時間計算量は O(n²) となります。要素数が多い配列では処理が遅くなる点が弱点です。

方法2: ソートを利用する

配列をあらかじめソートしておくと、同じ値どうしが連続して並ぶようになります。これにより、隣接する要素同士を比較するだけで重複を検出できるため、効率的に一意の要素を取り出せます。

#include <bits/stdc++.h>
using namespace std;

void printDistinctElements(int arr[], int n) {
    sort(arr, arr + n);
    for (int i = 0; i < n; i++) {
        while (i < n - 1 && arr[i] == arr[i + 1])
            i++;
        cout << arr[i] << "\t";
    }
}

int main() {
    int arr[] = {1, 5, 7, 12, 1, 6, 10, 7, 5};
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << "Distinct elements of the array are :\n";
    printDistinctElements(arr, n);
    return 0;
}

実行結果

Distinct elements of the array are −
1 5 6 7 10 12

この方法の時間計算量は O(n log n)(ソートのコストが支配的)です。ただし、元の配列の順序が失われ、また配列自体が書き換えられる点には注意が必要です。

方法3: unordered_setで訪問済み要素を管理する(推奨)

最も効率的なのが、ハッシュセットである std::unordered_set を使って「すでに出力した要素」を記録する方法です。配列を先頭から走査し、セットに未登録の要素だけを出力すると同時にセットへ挿入していきます。これにより、元の順序を保ちながら O(n) の時間計算量で処理できます。

#include <bits/stdc++.h>
using namespace std;

void printDistinctElements(int arr[], int n) {
    unordered_set<int> visited;
    for (int i = 0; i < n; i++) {
        if (visited.find(arr[i]) == visited.end()) {
            visited.insert(arr[i]);
            cout << arr[i] << "\t";
        }
    }
}

int main() {
    int arr[] = {1, 5, 7, 12, 1, 6, 10, 7, 5};
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << "Distinct numbers of the array are :\n";
    printDistinctElements(arr, n);
    return 0;
}

実行結果

Distinct numbers of the array are −
1 5 7 12 6 10

3つの方法の比較まとめ

方法時間計算量特徴
二重ループO(n²)実装は簡単だが、大きな配列では低速
ソート利用O(n log n)高速だが元の順序が失われる
unordered_setO(n)最速かつ元の順序を保持できる

パフォーマンスと順序の保持を両立したい場合は、方法3の unordered_set を使う手法がベストチョイスです。一方、小規模なデータや学習目的であれば、シンプルな二重ループでも十分実用的です。用途に応じて適切な方法を選びましょう。

  1. C++で始点から終点までのすべての経路を出力する方法|深さ優先探索(DFS)による実装

    この記事では、有向グラフが与えられたときに、始点(ソース)から終点(デスティネーション)までのすべての経路を出力する問題を、C++で解く方法を解説します。有向グラフとは?有向グラフとは、各辺に向きが定められており、頂点Aから頂点Bへと一方向に進むことができるグラフのことです。逆向き(BからA)には、対応する逆向きの辺が存在しない限り移動できません。問題の例具体例を使って問題を理解しましょう。下図のようなグラフを考えます。始点を「K」、終点を「P」とした場合の出力は次のようになります。出力:K -> T -> Y -> A -> P K -> T -> Y -

  2. Pythonで整数配列の重複を除去し、個別の要素だけを出力する方法

    整数型の配列が与えられ、その中には重複した要素が含まれている場合があります。この記事では、重複を取り除いて個別(ユニーク)な値だけを出力するPythonプログラムを解説します。 実行例 入力:A = [1, 2, 3, 4, 2, 3, 5, 6] 出力:[1, 2, 3, 4, 5, 6] アルゴリズム このプログラムは次の手順で動作します。 配列の要素を入力として受け取ります。 各要素を先頭から順番に1つずつ取り出します。 取り出した要素が、それ以前にすでに出力されたものかどうかを確認します。 初期値0のフラグ変数を用意し、すでに表示済みなら1、未表示なら0のままにします。 フラ