我正在尝试创建一个从随机生成的点返回最接近的对的算法。我已经完成了算法,但算法的分而治之方法并不比蛮力方法快得多。我该怎么做才能优化代码,使其在(n log n)时间返回?
<table>
<thead>
<tr>
<th class=""></th>
<th class="week" data-week="15">15</th>
<th class="week" data-week="16">16</th>
<th class="week" data-week="17">17</th>
<th class="week" data-week="18">18</th>
<th class="week" data-week="19">19</th>
</tr>
</thead>
<tbody>
<tr>
<td>Stina (1)</td>
<td data-id="40">10</td>
<td data-id="12">20</td>
<td data-id="13">40</td>
<td data-id="14">45</td>
<td data-id="15">40</td>
</tr>
<tr>
<td>Linda (2)</td>
<td data-id="0">0</td>
<td data-id="0">0</td>
</tr>
<tr>
<td>Lasse (3)</td>
<td data-id="21">5</td>
<td data-id="22">39</td>
<td data-id="23">40</td>
<td data-id="24">40</td>
</tr>
</tbody>
</table>
答案 0 :(得分:1)
使用以下方法更改minDisSimple。你可以获得更多的表现。
static double minDisSimple() {
// A straightforward method for computing the distance
// of the two closest points in plane[0..N-1].
// to be completed
double midDis = Double.POSITIVE_INFINITY;
double temp;
for (int i = 0; i < N - 1; i++) {
for (int j = i + 1; j < N; j++) {
temp = plane[i].distance(plane[j]);
if (temp < midDis) {
midDis = temp;
}
}
}
return midDis;
}
对于少量积分的性能明智简单的方法是好的但是分数更大的分数和征服是好的。尝试使用10,100,1000,10000,100000,1000000的点数。
答案 1 :(得分:0)
minDisDivideConquer()
中的一个关键方面是构造辅助数组T
的循环遍历所有N
个点。由于总共有O(N)
个递归调用,因此每次都会通过所有N
个点导致O(N^2)
的复杂性,相当于简单算法的复杂度。
循环实际上应该只考虑索引在low
和high
之间的点。此外,它可以分为两个独立的循环,从mid
(向前和向后)开始,并在检查的距离已经太大时中断。
{4}或更多点情况下minDisDivideConquer()
方法的另一个可能的改进是防止查看已在递归调用中考虑的对。
如果我的理解是正确的,那么数组T
包含那些在x轴上与中点足够接近的点,这样T
中的一对点就有可能生成一个点距离小于单个半套的距离。
但是,没有必要查看mid
之前或mid
之后的两个点(因为在递归调用中已经考虑过这些对)。
因此,可能的优化是构建两个列表T_left
和T_right
(而不是T
)并检查点对之间的距离,使得一个位于{{ 1}},另一个在右边。
这样,我们只会使用mid
查看|T| * (|T| - 1) / 2
对,而不是计算|T_left| * |T_right|
距离。该值最多为|T_left| + |T_right| = |T|
,即距离比以前少2倍(这是最坏的情况,但实际的对数也可以小得多,包括零)。