C++で配列内の全要素ペアのk番目に小さい差を求めるプログラム
問題概要
いくつかの整数を含むリストが与えられます。配列内のすべての値のペアについて差を計算し、その中からk番目に小さい差を見つける必要があります。インデックスは0から始まり、値kは入力として与えられます。
例えば、入力が numbers = {2, 6, 4, 8}、k = 2 の場合、出力は 2 になります。
各ペア間の差は以下の通りです。
- (2, 6) = 4
- (2, 4) = 2
- (2, 8) = 6
- (6, 4) = 2
- (6, 8) = 2
- (4, 8) = 4
これらの値をソートすると「2, 2, 2, 4, 4, 6」となり、2番目に小さい値は 2 です(インデックスは0から開始)。
解法のアプローチ:二分探索
この問題は、差の候補値に対して二分探索を行うことで効率的に解けます。「mid以下の差を持つペアの個数」を数え、それがk以上であれば答えはmid以下、そうでなければmidより大きい、という性質を利用します。具体的な手順は以下の通りです。
- k を1増やす(0始まりのインデックスに対応させるため)
- 配列 input をソートする
- le := 0 とする
- ri := inputの最後の要素 − inputの最初の要素 とする
- le < ri の間、以下を繰り返す:
- mid := (le + ri) / 2
- tmp := 0、lp := 0 とする
- i := 1 から input のサイズ未満まで、i を1ずつ増やしながら繰り返す:
- input[i] − input[lp] > mid の間、lp を1ずつ増やす
- tmp := tmp + i − lp
- もし tmp >= k ならば、ri := mid とする
- そうでなければ、le := mid + 1 とする
- le を返す
実装例
理解を深めるために、以下のC++実装を見てみましょう。
#include<bits/stdc++.h>
using namespace std;
int solve(vector<int>& input, int k) {
k++;
sort(input.begin(), input.end());
int le = 0;
int ri = input.back() - input[0];
while (le < ri) {
int mid = (le + ri) / 2;
long long tmp = 0;
int lp = 0;
for (int i = 1; i < input.size(); i++) {
while (input[i] - input[lp] > mid)
lp++;
tmp += i - lp;
}
if (tmp >= k)
ri = mid;
else
le = mid + 1;
}
return le;
}
int main() {
vector<int> numbers = {2, 6, 4, 8};
cout<< solve(numbers, 2) <<endl;
return 0;
}入力
vector<int> numbers = {2, 6, 4, 8};
cout<< solve(numbers, 2) <<endl;出力
2
計算量
ソートに O(n log n)、二分探索の各ステップではソート済み配列を走査してペア差の個数を数えるのに O(n) かかるため、全体の時間計算量は O(n log n + n log D) となります(D は最大差と最小差の範囲)。すべてのペアを列挙する O(n²) の素朴な手法と比べて、大幅に効率的である点がこのアプローチの大きな利点です。
-
C#で配列から最小値を取得する方法:Min()メソッドの使い方
C#では、配列の中から最小の要素を簡単に取得できます。そのために使用するのが、System.Linq名前空間に含まれるMin()メソッドです。配列の宣言まず、整数型の配列を宣言します。int[] arr = { 5, 9, 2, 7 };Min()メソッドで最小値を取得する配列から最小の要素を取得するには、Min()メソッドを呼び出すだけでOKです。arr.Min();完全なコード例以下は、配列内の最小値を求めてコンソールに出力する完全なサンプルコードです。using System; using System.Linq; class Demo { stat
-
C#プログラムで配列内のK番目に小さい要素を見つける方法
はじめにC#では、配列を昇順に並べ替えてからインデックスを指定するだけで、K番目に小さい要素を簡単に求められます。本記事では、Array.Sort()メソッドを使った基本的な実装方法を、サンプルコード付きでわかりやすく解説します。ステップ1:配列を宣言するまず、対象となる整数型の配列を宣言します。int[] a = new int[] { 65, 45, 32, 97, 23, 75, 59 };ステップ2:配列をソートするここでは5番目に小さい整数を求めるものとします。まずArray.Sort()メソッドを使って配列を昇順に並べ替えます