C++でハッシュ(unordered_map)を使って配列を縮小形式に変換する方法
このチュートリアルでは、ハッシュ(連想配列)を活用して、配列を縮小形式(reduced form)に変換するC++のプログラムについて解説します。
縮小形式への変換とは、与えられた配列の要素を、元の大小関係(相対的な順序)を保ったまま 0 ~ n-1 の範囲の値に置き換える処理のことです。例えば、配列 {10, 20, 15, 12, 11, 50} の場合、最も小さい要素「10」は「0」に、次に小さい「11」は「1」に、というように各要素をその順位へと変換します。
アルゴリズムの流れ
- 元の配列をコピーし、昇順にソートします。
- ソート済みの各要素に対して、0 から始まる順位を割り当て、「要素 → 順位」のペアとして
unordered_map(ハッシュテーブル)に格納します。 - 元の配列の各要素を、ハッシュテーブルから取得した順位で上書きします。
ハッシュテーブルを使うことで、各要素の順位を O(1) で高速に参照できるのがポイントです。
サンプルコード
#include <bits/stdc++.h>
using namespace std;
// 配列を縮小形式に変換する関数
void convert(int arr[], int n){
// 配列の要素をコピーしてソート
int temp[n];
memcpy(temp, arr, n*sizeof(int));
sort(temp, temp + n);
// ハッシュテーブル(unordered_map)を作成
unordered_map<int, int> umap;
int val = 0;
for (int i = 0; i < n; i++)
umap[temp[i]] = val++;
// 元の配列の要素をハッシュテーブルの値で置き換え
for (int i = 0; i < n; i++)
arr[i] = umap[arr[i]];
}
void print_array(int arr[], int n) {
for (int i=0; i<n; i++)
cout << arr[i] << " ";
}
int main(){
int arr[] = {10, 20, 15, 12, 11, 50};
int n = sizeof(arr)/sizeof(arr[0]);
cout << "Given Array :\n";
print_array(arr, n);
convert(arr , n);
cout << "\nConverted Array:\n";
print_array(arr, n);
return 0;
}実行結果
Given Array : 10 20 15 12 11 50 Converted Array: 0 4 3 2 1 5
計算量について
このアルゴリズムの時間計算量は、ソート処理が支配的となるため O(n log n) です。ハッシュテーブルへの登録と参照はそれぞれ平均 O(n)、O(1) で行えるため、全体のボトルネックにはなりません。また、補助配列とハッシュテーブルの分だけ余分なメモリが必要となり、空間計算量は O(n) となります。
-
C++でint型をstring型に変換する方法を解説
整数(int)を文字列(string)に変換したい場合、いくつかの方法があります。まずはC言語由来のitoa関数を使う方法から見ていきましょう。 itoa関数を使う方法 itoaは「integer to ASCII」の略で、整数値を文字列に変換するC言語の関数です。以下のように使用します。 例 #include<iostream> int main() { int a = 10; char *intStr = itoa(a); string str = string(intStr); cout << str; } 出力 このコードを実行す
-
【C++入門】配列を関数に渡す3つの方法をわかりやすく解説
C++では、配列全体をそのまま関数の引数として渡すことはできません。しかし、インデックスを付けずに配列名を指定することで、配列へのポインタを渡すことができます。これは「配列名は先頭要素へのポインタに読み替えられる(配列の減衰)」というC++の仕組みによるものです。1次元配列を関数の引数として渡したい場合は、以下の3つのいずれかの方法で関数の仮引数を宣言します。どの方法でも、コンパイラに対して「整数型のポインタを受け取る」という情報が伝わるため、動作結果はすべて同じになります。配列を関数に渡す3つの宣言方法1. ポインタとして仮引数を宣言するvoid myFunction(int *param)