C++で1つの数値だけを含む最長区間を求めるアルゴリズム
問題概要
相異なる整数のリスト nums が与えられます。この中から、リスト内の数値を最大1つしか含まない区間 [start, end](両端を含む)のうち、最も長いもののサイズを求めましょう。
例えば、nums = [10, 6, 20] が入力された場合、出力は 99990 となります。これは、最も長い区間が [11, 100000] であり、この区間には 20 のみが含まれるためです。
解法のアプローチ
この問題は、配列をあらかじめソートしておき、各数値について「その数値のみを含む区間」を隣接する数値の位置から求めることで効率よく解けます。手順は以下の通りです。
- ret := −inf(答えを保持する変数)
- end := 100000(探索範囲の上限)
- prev := 1(直前の数値を保持する変数)
- 配列 nums をソートする
- n := nums のサイズ
- i := 0 から nums のサイズ未満の間、i を1ずつ増やしながら次を繰り返す
- i + 1 < n の場合:high := nums[i + 1] − 1
- そうでなければ:high := end
- i − 1 ≥ 0 の場合:low := prev + 1
- そうでなければ:low := prev
- prev := nums[i]
- ret := max(high − low + 1, ret)
- ret を返す
アルゴリズムのポイント
ソート後の各要素に対して、「前の要素 + 1」から「次の要素 − 1」までの範囲を見ることで、その要素だけを含む区間の長さを正確に計算できます。先頭の要素では始点を 1、末尾の要素では終点を 100000 とすることで、探索範囲の両端にも対応します。各区間の長さは high − low + 1 で表され、その最大値が最終的な答えとなります。
C++による実装例
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int solve(vector<int> &nums) {
int ret = INT_MIN;
int end = 100000;
int prev = 1;
sort(nums.begin(), nums.end());
int n = nums.size();
int low, high;
for (int i = 0; i < nums.size(); i++) {
if (i + 1 < n) {
high = nums[i + 1] - 1;
} else
high = end;
if (i - 1 >= 0) {
low = prev + 1;
} else
low = prev;
prev = nums[i];
ret = max(high - low + 1, ret);
}
return ret;
}
};
main() {
Solution ob;
vector<int> v = {10, 6, 20};
cout << (ob.solve(v));
}
入力例
{10, 6, 20}
出力例
99990
計算量
ソートに O(n log n)、その後の線形走査に O(n) の時間がかかるため、全体の計算量は O(n log n) となります。追加のメモリ使用量もごくわずかで、非常に効率的な解法です。
-
C++で質素数(Frugal Number)を判定する方法【サンプルコード付き】
この記事では、正の整数 N が与えられたときに、その数が質素数(Frugal Number)であるかどうかを判定するプログラムを C++ で作成する方法を解説します。 質素数とは? 質素数(FRUGAL NUMBER)とは、その数自身の桁数が、素因数分解による表現の桁数よりも厳密に大きい数のことです。 例:625 の場合 625 を素因数分解すると 54 となります。 625 自身の桁数:3 桁 54 の表現の桁数:2 桁 3 は 2 よりも厳密に大きいため、625 は質素数です。 最初のいくつかの質素数:125、128、243、256、343、512、625 など 問題を理解するための具
-
C++で五胞体数(ペンタトープ数)を求める方法
五胞体数とは? 五胞体数(ペンタトープ数)は、パスカルの三角形の第5の対角線上に現れる数列として知られています。この数列を定義するには、パスカルの三角形に少なくとも5つの数が必要となるため、数列の最初の数はパスカルの三角形の第4行である 1 4 6 4 1 から始まります。 本チュートリアルでは、n番目の五胞体数を求める方法を解説します。まずは具体的な例を見てみましょう。 入力 : 1出力 : 1入力 : 4出力 : 35 以下の図から出力を確認できます。 この問題は数列に関するものなので、解法ではまず数列のパターンを見つけることから始めます。 解法のアプローチ このプログラムでは、数列の