C・C++で配列の2番目に大きい値を求める
このレッスンでは、並べ替えをせず、1回の走査で配列の中の異なる値のうち2番目に大きいものを見つけます。
はじめに
2番目に大きい値を求めるのにいちばん思いつきやすいのは配列を並べ替えることですが、それでは余計な時間がかかります。代わりに、最大値と同じ値は無視しながら、1回の走査で大きいほうから2つの値を追いかければ十分です。
大切なポイント
- コンパイラの警告(compiler warning)を有効にして、すべての警告を直しましょう。
- それぞれの値のデータ型と寿命(lifetime)をしっかり理解しましょう。
- 入力データと配列のインデックスの範囲は必ずチェックしましょう。
CとC++のコード例
C
main.c
#include <limits.h>
#include <stdio.h>
int main(void) {
int values[] = {7, 23, 12, 23, 9}, first = INT_MIN, second = INT_MIN;
// Maintain the two largest distinct values.
for (int i = 0; i < 5; ++i) { int value = values[i]; if (value > first) { second = first; first = value; } else if (value > second && value != first) second = value; }
printf("second=%d\n", second);
}
second=12
C++
main.cpp
#include <iostream>
#include <limits>
#include <vector>
int main() {
std::vector values{7, 23, 12, 23, 9}; int first = std::numeric_limits<int>::min(), second = first;
// Maintain the two largest distinct values.
for (int value : values) { if (value > first) { second = first; first = value; } else if (value > second && value != first) second = value; }
std::cout << "second=" << second << '\n';
}
second=12
CとC++の比較
変数firstとsecondは、int型の最小値INT_MINから始めます。firstより大きい値が見つかると、firstの古い値がsecondに移ります。2つの間にあってfirstと違う値が見つかったときは、secondだけを更新します。そのため2回出てくる23が結果を狂わせることはなく、2番目に大きい値は12です。
C
Cは小さな手続き型の関数を使い、データがメモリ上でどう表されるかをそのまま見せます。
C++
C++は低レベルの操作もできるまま、ライブラリの型やより安全な抽象化を加えます。
発展問題
両方のバージョンを実行し、コードを書き換えて、それぞれの言語がもたらす安全性の違いを観察しましょう。
- 不正な入力や境界の値で試しましょう。
- 警告を増やすフラグ-Wall -Wextra -Wpedanticを付けてコンパイルしましょう。
- 共通の宣言はヘッダーファイルに、実装は別のファイルに分けましょう。
チャレンジで練習する
このレッスンの内容を使って実際の問題を解きましょう。各チャレンジはブラウザで動き、すぐにテストされ、AI のレビューも受けられます。
すべてのチャレンジ