1. イテレータとペアの値へのアクセス方法の違い
イテレータを介して値にアクセスする場合と、ループ内で直接ペアオブジェクトにアクセスする場合で、ドット演算子とアロー演算子の使い分けが必要です。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
std::unordered_map hash_map;
for(int i = 0; i < nums.size(); i++) {
// ハッシュマップ内でターゲット値を検索
auto it = hash_map.find(target - nums[i]);
if(it != hash_map.end()) {
// イテレータの指す要素の値にアクセス
return {it->second, i};
}
// 見つからなければ、要素とそのインデックスをマップに追加
hash_map[nums[i]] = i;
}
return {};
}
};
class Solution {
public:
bool uniqueOccurrences(vector<int>& arr) {
unordered_map hash_map;
unordered_set<int> unique_counts;
for(int i = 0; i < arr.size(); i++){
hash_map[arr[i]]++;
}
for(const auto& kv_pair : hash_map){
// ペアオブジェクトの値にアクセス
unique_counts.insert(kv_pair.second);
}
return unique_counts.size() == hash_map.size();
}
};
上記の最初のコードでは、`it`はハッシュマップのイテレータであり、その指す要素(キーと値のペア)にアクセスするため、アロー演算子(`->`)を使用します。
二つ目のコードでは、`kv_pair`は`std::pair`オブジェクトそのものであり、そのメンバ変数にアクセスするため、ドット演算子(`.`)を使用します。
2. マップへの挿入と要素の存在確認
マップへの挿入には、insertメソッドと直接代入の二つの方法があります。
// 方法1: insertメソッドを使用
my_map.insert(std::make_pair(key, value));
// 方法2: 直接代入(推奨)
my_map[key] = value;
countメソッドは、指定されたキーが存在するかどうかを確認し、存在すれば1、存在しなければ0を返します。
if (my_map.count(some_key)) {
// キーが存在する
}
3. swap関数の用途
std::swap関数は、主にコンテナ内の二つの要素を交換するために使用されます。
std::vector<int> data_vec = {1, 2, 3, 4, 5};
std::swap(data_vec[1], data_vec[3]); // data_vecは{1, 4, 3, 2, 5}になる
4. sizeメソッドの使い方
std::string、std::vector、std::map、std::set、std::queueなどのコンテナは、.size()メソッドで要素数を取得できます。
しかし、Cスタイルの配列(例: int arr[10])にはこのメソッドはありません。その場合、sizeof(arr)/sizeof(arr[0])を使用して要素数を計算します。
5. 文字列操作関数
substr(開始位置, 長さ): 文字列の部分文字列を取得します。reverse(イテレータの開始, イテレータの終了): イテレータで指定された範囲の要素を反転させます。
std::string text_str = "hello";
std::string sub = text_str.substr(1, 3); // "ell"
std::reverse(text_str.begin(), text_str.end()); // "olleh"
6. find関数の使い分けと時間計算量
異なるコンテナに対して、異なるfind関数が提供されています。
- 連想コンテナ(ハッシュテーブル、木):
map.find(key)やset.find(key)。平均的な時間計算量はO(1)(ハッシュテーブル)またはO(log n)(平衡二分木)です。 - シーケンシャルコンテナ(ベクタ、リスト):
std::find(vec.begin(), vec.end(), value)。最悪のケースの時間計算量はO(n)です。
7. 整数の平均値計算(データ型の制約あり)
32ビットの符号なし整数の配列の平均値を計算する際、64ビット整数や浮動小数点数を使用できない場合のテクニックです。
#include <iostream>
#include <vector>
using namespace std;
uint32_t calculateAverage(const vector& input_vec) {
uint32_t quotient_sum = 0;
uint32_t remainder_sum = 0;
uint32_t n = input_vec.size();
for (size_t i = 0; i < n; ++i) {
quotient_sum += input_vec[i] / n;
remainder_sum += input_vec[i] % n;
}
return quotient_sum + remainder_sum / n;
}
int main() {
vector test_data = {41, 4, 7, 13};
uint32_t avg = calculateAverage(test_data);
cout << "平均値: " << avg << endl;
return 0;
}
8. 時間計算量の基本
- 二分探索: O(log n)
- クイックソート: O(n log n)
9. スタックとキューの基本操作
- スタック:
stack.push(),stack.pop(),stack.top()。先入後出(LIFO)。 - キュー:
queue.push(),queue.pop(),queue.front(),queue.back()。先入先出(FIFO)。 - スタックでキューを実装: 二つのスタック(入力用と出力用)を使用します。
- キューでスタックを実装: 二つのキュー(一つはバックアップ用)を使用します。
10. 関数の戻り値の取り扱い
関数の戻り値を変数に格納する必要は必ずしもありません。直接利用することも可能です。
int max_val = getMax(a, b); // 変数に格納
cout << getMax(a, b); // 直接出力
11. 型変換
整数を文字列に変換するには、std::to_string()関数を使用します。
int number = 123;
std::string str_num = std::to_string(number);
12. 文字列配列の定義
固定長の文字列配列は、定数として定義するのが一般的です。
const std::string roman_numerals[] = {
"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"
};
13. ビットシフト演算子の優先順位に注意
ビットシフト演算子(<<, >>)の優先順位は低いため、複雑な式では括弧で明確にする必要があります。
int a = 1, b = 2;
int result = (a << 2) + b; // 正しい
// int wrong_result = a << 2 + b; // 予期しない結果になる可能性あり
14. カスタム比較関数を用いたソート
std::sortに比較関数オブジェクトを渡すことで、独自のソートロジックを実装できます。
#include <algorithm>
#include <vector>
#include <cmath>
bool cmp_func(int a, int b) {
return std::abs(a) > std::abs(b);
}
int main() {
std::vector<int> my_vec = {-3, 1, -2, 4, -5};
std::sort(my_vec.begin(), my_vec.end(), cmp_func);
// my_vecは{-5, -3, -2, 1, 4}となる
}
15. reverse関数
コンテナの要素を反転させるには、std::reverseを使用します。
std::vector<int> numbers = {1, 2, 3, 4, 5};
std::reverse(numbers.begin(), numbers.end()); // numbersは{5, 4, 3, 2, 1}になる
16. 優先度付きキュー(ヒープ)
デフォルトでは最大ヒープですが、比較関数を指定することで最小ヒープにできます。
#include <queue>
#include <vector>
int main() {
// 最小ヒープの宣言
std::priority_queue min_heap;
min_heap.push(10);
min_heap.push(5);
min_heap.push(20);
// top()は常に最小値(5)を返す
}