C++
 Computer >> コンピューター >  >> プログラミング >> C++

【C++】配列内のK番目に小さいペア距離を求める方法

問題の概要

整数型の配列が与えられたとき、すべてのペアの中からk番目に小さい距離を求めることを考えます。ここで、ペア (A, B) の距離とは、A と B の差の絶対値(|A − B|)を指します。

例として、入力が [1, 3, 8] の場合を見てみましょう。考えられるすべてのペアとその距離は以下の通りです。

  • [1, 3] → 距離 2
  • [3, 8] → 距離 5
  • [1, 8] → 距離 7

このとき k = 2 であれば、2番目に小さい距離は 5(8 − 3)となります。

解法のアプローチ

この問題は、カウント配列(度数分布)を使ったシンプルな手法で解くことができます。手順は以下の通りです。

  1. 配列のサイズを n、配列内の最大値を x とします。
  2. サイズ x + 1 のカウント配列 cnt を用意します。
  3. すべてのペア (i, j)(i < j)について、cnt[|nums[j] − nums[i]|] を 1 ずつ増やしていきます。
  4. 距離 0 から x まで順に走査し、累積カウントが k 以上になった時点の距離が答えとなります。

この方法では、各ペアの距離を直接数え上げるため、二重ループによる O(n²) の計算が必要になりますが、実装が非常に直感的で理解しやすいのが大きな特徴です。

C++での実装例

それでは、実際のコードを見てみましょう。

#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
    int smallestDistancePair(vector<int>& nums, int k) {
        int n = nums.size();
        int x = 0;
        for(int i = 0; i < n; i++)x = max(x, nums[i]);
        vector <int> cnt(x + 1);
        for(int i = 0 ; i < n; i++){
            for(int j = i + 1; j < n; j++){
                cnt[abs(nums[j] - nums[i])]++;
            }
        }
        for(int i = 0; i <= x; i++){
            if(cnt[i] >= k)return i;
            k -= cnt[i];
        }
        return x;
    }
};
main(){
    Solution ob;
    vector<int> v = {1,3,8};
    cout << (ob.smallestDistancePair(v, 2));
}

入力

{1,3,8}

出力

5

コードのポイントと計算量

このアルゴリズムは、まず配列内の最大値を求めてカウント配列のサイズを決定し、次にすべてのペアの距離を記録、最後に小さい距離から順に数えていくことで、k番目に小さい距離を特定します。

  • 時間計算量: O(n² + x) — ペアの列挙に O(n²)、カウント配列の走査に O(x)
  • 空間計算量: O(x) — 最大値に依存するカウント配列が必要

なお、より大規模な入力に対しては、二分探索とスライディングウィンドウを組み合わせることで O(n log W + n log n) に高速化する手法も知られています。要素数が少なく値の範囲が限られている場合は、本記事のようなカウント配列方式が最もシンプルで効果的です。

  1. 【C++】二分探索木(BST)でk番目に小さい要素を検索する方法

    問題概要二分探索木(BST)と整数 k が入力として与えられたとき、木の中で k番目に小さい要素 を見つける問題を解説します。例えば、以下のようなBSTを考えてみましょう。この木に対して k = 3 を指定した場合、出力は 15 になります。木の要素を昇順に並べると「9, 13, 15, 17, 19, 25, 27」となり、3番目の値が15であるためです。アルゴリズムの考え方二分探索木には、「中順走査(in-order traversal)」を行うと要素が昇順に訪問されるという重要な性質があります。この性質を利用し、走査中に訪問したノード数をカウントしていき、k番目に到達した時点でそのノード

  2. 【C++】しきい値距離以内で到達できる都市数が最も少ない都市を求める方法

    問題概要0からn-1までの番号が付けられたn個の都市があるとします。配列edgesが与えられ、edges[i] = [fromi, toi, weighti] は都市fromiとtoiの間を結ぶ双方向の重み付き辺を表します。さらに、整数の距離しきい値(distance threshold)が与えられます。このとき、何らかの経路を辿って到達でき、かつその距離がしきい値以下となる都市の数が最も少ない都市を求めてください。該当する都市が複数存在する場合は、その中で最も番号の大きい都市を返します。入力例次のような入力を考えてみましょう。n = 4、距離しきい値も4であるとき、出力は3になります。その理