C++で配列内の最長の山(Mountain)を求めるアルゴリズム
配列 A の任意の連続する部分配列 B は、以下の性質を満たすとき「山(マウンテン)」と呼ばれます。
- B のサイズが 3 以上であること
- 0 < i < B.length - 1 を満たすある i が存在し、B[0] < B[1] < ... B[i-1] < B[i] > B[i+1] > ... > B[B.length - 1] となること(要素が一度単調に増加した後、単調に減少する形状であること)
ここで、整数の配列 A が与えられたとき、その中で最も長い山の長さを求めることを考えます。山がひとつも存在しない場合は 0 を返します。たとえば入力が [2,1,4,7,3,2,5] の場合、答えは 5 になります。このとき最も大きな山は [1,4,7,3,2] であり、その長さは 5 です。
解法のアプローチ
この問題は、配列を左から順に走査しながら「上り坂」と「下り坂」を検出することで解けます。具体的には、次の手順に従います。
- ret := 0、n := 配列 a のサイズ と初期化します。
- i を 0 から n - 1 まで、処理終了後は i = j + 1 として進めながら、以下を繰り返します。
- j := i とし、down := false、up := false で初期化します。
- j + 1 < n かつ a[j + 1] > a[j] の間、up := true として j を 1 増やします(上り坂を探索)。
- up が true かつ j + 1 < n かつ a[j + 1] < a[j] の間、down := true として j を 1 増やします(下り坂を探索)。
- up と down がどちらも true の場合、山が成立しているので ret := max(j - i + 1, ret) として最大長を更新し、j を 1 減らして次の走査位置を調整します。
- 最後に ret を返します。
理解を深めるために、以下の C++ 実装を見てみましょう。
例(C++ 実装)
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int longestMountain(vector<int>& a) {
int ret = 0;
int n = a.size();
int j;
for(int i = 0; i < n; i = j + 1){
j = i;
bool down = false;
bool up = false;
while(j + 1 < n && a[j + 1] > a[j]) {
up = true;
j++;
}
while(up && j + 1 < n && a[j + 1] < a[j]){
down = true;
j++;
}
if(up && down){
ret = max(j - i + 1, ret);
j--;
}
}
return ret;
}
};
main(){
vector<int> v = {2,1,4,7,3,2,5};
Solution ob;
cout << (ob.longestMountain(v));
}
入力
[2,1,4,7,3,2,5]
出力
5
計算量
このアルゴリズムでは、外側のループが進むたびに i は処理済みの区間の直後へジャンプするため、各要素は高々一度しか訪問されません。したがって、時間計算量は O(n)、追加で必要な空間計算量は O(1) と非常に効率的です。
-
C++で文字列の配列を定義・操作する方法を解説
この記事では、C++において文字列の配列をどのように定義し、扱うのかを詳しく解説します。C言語との違い:文字列配列の基礎知識C言語には文字列型が存在しないため、文字列はchar型の配列(文字配列)として表現する必要がありました。そのため、複数の文字列をまとめて管理する「文字列の配列」を作るには、2次元のchar型配列を用意し、各行に異なる文字列を格納するという手法が取られていました。これは直感的ではなく、コードも冗長になりがちでした。一方、C++ではstd::stringクラスが標準ライブラリとして提供されています。このクラスのオブジェクトを使えば、文字列データを効率的かつ安全に格納・操作でき
-
C++で配列を並べ替える方法|選択ソートの仕組みと実装例を解説
C++では、さまざまなソート(並べ替え)アルゴリズムを使って配列を整列できます。ソート済みの配列とは、数値の大小順やアルファベット順など、何らかの基準に従って要素が並び替えられた配列のことです。代表的なソートアルゴリズムには、バブルソート、挿入ソート、選択ソート、マージソート、クイックソート、ヒープソートなどがあります。本記事では、その中でも構造がシンプルで理解しやすい「選択ソート」を取り上げ、実際のコード例とともに詳しく解説していきます。 選択ソートとは? 選択ソートは、未ソート部分の中から最小値を繰り返し探し出し、それを未ソート部分の先頭にある要素と交換することで、配列全体を昇順に整列さ