1) 上一篇求最大连续子数组之和了解到分治策略之后,做本题时先是找到中间界线,依然分成三部分,左边集合、右边集合、两个点分别在左边和右边的集合的情况。前两种情况不断递归,直到该集合内只有两个点,则求两点之间距离并返回,第三种情况如果常规来做,则是左边集合中的每一个点都要对应求到右边集合中每个点的距离,比较出其中最小的,此处O((n/2)^2),时间复杂度依然是n^2层次,于是继续优化,先筛选出左边集合中到中间界线的x的距离已经大于当前最小距离的点,同理,筛选并去掉右边集合x的距离已经大于当前最小距离的点,然后提交,TLE(Time Limit Exceeded),再将当前集合,左边集合中到中间界线的y的距离已经大于当前最小距离的点,去掉,(在结构体中另开一个Int做一下标记即可)同理右边集合也是如此,再提交,AC
我自己的思路只是做到分治,但是停留在n^2的层次,看了其他人的思路之后,才知道可以进行后两次优化,而且没想到这样做会成功,成功的原因是,在上面所述第三种情况中,因为前提已经限定一个点在左边,另一个点在右边,则由此划出了一个区域,即在每个点的x值上,应该是在中界线往左minn距离,和中界线往右minn距离的范围内,(minn距离是另外两种情况中的最小对的距离,第三种情况若对则存在的最小点对距离必定小于minn,若不存在则返回minn),但这并不能保证,两个点x方向距离很近,但y反向很远的问题,我们似乎应该将y方向上大于minn的点也给去掉,然后进行两层fou循环,不断求两点间距离并更新最小值,这样的做法,看起来似乎还是让这一步的算法处于O(n^2)的层次,但实际上,在中界线上确定某个点,该点往左、右、上、下所划定的范围内,点的个数是有限的,是不大于8个的(因为必须保证一点在左、一点在右,则自然保证了同一边的点互相之间是必须保持一定距离的,否则就不会属于第三种情况。换句话说,小于minn距离的点对有限而绝不会无限多),于是在两层for循环中,如果两个点y的距离大于minn,就可以break了,相当于使内层循环控制在了O(1)的层次上,于是这一步的时间复杂度到了O(n),整个算法的时间复杂度,降为O(nlogn)。(参见《导论》33-4)