整数座標の制約により、問題が大幅に簡素化されると思います。これは私には O(n) のように見えます:
-空間内のすべての整数点の辞書を作成し、エントリを 0 に設定します。
- 各データポイントについて、半径 3 以内にある整数ポイントを見つけ、辞書の対応するエントリに 1 を追加します。これを行う理由は、その特定のデータポイントが内側にある円の中心になることができるポイントのセットが、そのデータポイントの周りの同じ半径を持つ円の整数制限であるためです。検索は、長さ 6 の正方形上にあるすべてのポイントに対して実行できます (内接ハイパーキューブ内のこれらのポイントは確実に内部にあるため、すべてのポイントを明示的に評価する必要はありません)。
- ディクショナリの最大値に対応する整数点、つまりほとんどのデータポイントが円の内側にある中心を返します。
編集:一部のコードは説明よりも優れていると思います。これは numpy と matplotlib で動作する python です。読むのが難しすぎてはいけません:
# -*- coding: utf-8 -*-
"""
Created on Mon Mar 11 19:22:12 2013
@author: Zah
"""
from __future__ import division
import numpy as np
import numpy.random
import matplotlib.pyplot as plt
from collections import defaultdict
import timeit
def make_points(n):
"""Generates n random points"""
return np.random.uniform(0,30,(n,2))
def find_centers(point, r):
"""Given 1 point, find all possible integer centers searching in a square
around that point. Note that this method can be imporved."""
posx, posy = point
centers = ((x,y)
for x in xrange(int(np.ceil(posx - r)), int(np.floor(posx + r)) + 1)
for y in xrange(int(np.ceil(posy - r)), int(np.floor(posy + r)) + 1)
if (x-posx)**2 + (y-posy)**2 < r*r)
return centers
def find_circle(n, r=3.):
"""Find the best center"""
points = make_points(n)
d = defaultdict(int)
for point in points:
for center in find_centers(point, r):
d[center] += 1
return max(d , key = lambda x: d[x]), points
def make_results():
"""Green circle is the best center. Red crosses are posible centers for some
random point as an example"""
r = 3
center, points = find_circle(100)
xv,yv = points.transpose()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_aspect(1)
ax.scatter(xv,yv)
ax.add_artist(plt.Circle(center, r, facecolor = 'g', alpha = .5, zorder = 0))
centersx, centersy = np.array(list(find_centers(points[0], r))).transpose()
plt.scatter(centersx, centersy,c = 'r', marker = '+')
ax.add_artist(plt.Circle(points[0], r, facecolor = 'r', alpha = .25, zorder = 0))
plt.show()
if __name__ == "__main__":
make_results()
結果:
緑色の円が最適です。赤い円は、ランダムな点の中心がどのように選択されるかを示しています。
In [70]: %timeit find_circle(1000)
1 loops, best of 3: 1.76 s per loop
In [71]: %timeit find_circle(2000)
1 loops, best of 3: 3.51 s per loop
In [72]: %timeit find_circle(3000)
1 loops, best of 3: 5.3 s per loop
In [73]: %timeit find_circle(4000)
1 loops, best of 3: 7.03 s per loop
私の本当に遅いマシンで。行動は明らかに直線的です。