C++で原点に最も近いK個の点を見つけるアルゴリズムを解説
平面上に複数の点が与えられたとき、その中から原点(0, 0)に最も近いK個の点を求める問題を考えてみましょう。
例として、点 (3, 3)、(5, -1)、(-2, 4) の3点が与えられ、K = 2 とします。このとき原点に最も近い2点は (3, 3) と (-2, 4) になります。
解決のアプローチ
この問題は次の手順で解くことができます。
- 各点についてユークリッド距離を計算します。原点からの距離は √(x² + y²) で表されますが、大小比較だけであれば平方根の計算は不要なので、x² + y² の値をそのまま使えば十分です。
- 距離を基準に点のリストをソートします。
- ソート後のリストから先頭のK個の要素を取り出します。これが原点に最も近いK個の点となります。
C++での実装例
#include<iostream>
#include<algorithm>
using namespace std;
class Point {
private:
int x, y;
public:
Point(int x = 0, int y = 0) {
this->x = x;
this->y = y;
}
void display() {
cout << "(" << x << ", " << y << ")";
}
friend bool comparePoints(Point &p1, Point &p2);
};
// 原点からの距離を比較する関数
bool comparePoints(Point &p1, Point &p2) {
float dist1 = (p1.x * p1.x) + (p1.y * p1.y);
float dist2 = (p2.x * p2.x) + (p2.y * p2.y);
return dist1 < dist2;
}
// 原点に最も近いK個の点を出力する関数
void closestKPoints(Point points[], int n, int k) {
sort(points, points + n, comparePoints);
for(int i = 0; i < k; i++) {
points[i].display();
cout << endl;
}
}
int main() {
Point points[] = {{3, 3}, {5, -1}, {-2, 4}};
int n = sizeof(points) / sizeof(points[0]);
int k = 2;
closestKPoints(points, n, k);
}
実行結果
(3, 3) (-2, 4)
コードのポイント
- comparePoints関数: 2つの点それぞれの x² + y² を計算し、どちらが原点に近いかを判定します。
friend宣言により、クラスのprivateメンバである x・y 座標にアクセスできるようにしています。 - sort関数: STLの
std::sortを使い、カスタム比較関数に基づいて点を昇順に並べ替えます。 - 計算量: ソートに O(n log n) の時間がかかります。データ数が非常に多い場合は、ヒープ(優先度付きキュー)を使うことで O(n log k) まで効率化することも可能です。
このように、ソートとカスタム比較関数を組み合わせるだけで、「原点に最も近いK個の点」をシンプルに求めることができます。
-
C++で三角形の重心を求めるプログラムの作成方法
この記事では、三角形の3つの頂点の座標を格納した2次元配列が与えられたときに、その三角形の重心を求めるC++プログラムの作成方法を解説します。 三角形の重心とは、三角形の3本の中線がすべて交わる点のことです。 また、三角形の中線とは、ある頂点と、その対辺(向かい合う辺)の中点を結ぶ線分のことを指します。 それでは、具体的な例を使って問題を確認してみましょう。 入力 (-3, 1), (1.5, 0), (-3, -4) 出力 (-1.5, -1) 説明 重心 (x, y) = ((-3 + 1.5 - 3) / 3, (1 + 0 - 4) / 3) = (-1.5, -1) 解法のアプロ
-
C++で二分木における最も近い葉ノードまでの距離を求める方法
二分木が与えられ、その葉ノードはそれぞれ異なるレベルに存在するとします。さらに、あるノードを指すポインタが与えられ、そのノードから最も近い葉ノードまでの距離を求める必要があります。例として、次のような二分木を考えてみましょう。この木における葉ノードは 2、-2、6 の3つです。もしポインタがノード -5 を指している場合、-5 から最も近い葉ノードまでの距離は 1 となります。解決のアプローチこの問題を解くには、次の手順で考えます。まず、指定されたノードを根とする部分木を走査し、その部分木内で最も近い葉ノードを見つけて距離を記録します。次に、木の根から全体を走査します。ノード x が左部分木に