该问题基于 leetcode 竞赛问题 ( https://doocs.github.io/leetcode/en/lc/3281/ )。可以将其简化为以下问题:设s为已排序数组,d为正整数,最小化 ( s [i]- s [j]+ d )/(ij)。其中 i>j。
大多数答案都是基于二分搜索来限制最优解,其时间复杂度取决于 max( s )-min( s )。那么,是否有可能构建一个相对于s大小线性/次二次的算法?
该问题基于 leetcode 竞赛问题 ( https://doocs.github.io/leetcode/en/lc/3281/ )。可以将其简化为以下问题:设s为已排序数组,d为正整数,最小化 ( s [i]- s [j]+ d )/(ij)。其中 i>j。
大多数答案都是基于二分搜索来限制最优解,其时间复杂度取决于 max( s )-min( s )。那么,是否有可能构建一个相对于s大小线性/次二次的算法?
您可以在 O(n log n) 时间内完成此操作。
s[i]
首先,请注意,如果我们要沿着高点绘制低点图s[i]+d
,那么我们的任务就是找到从低点到其右侧高点的斜率最小的线。当我们迭代高点时,我们可以确定其左侧的哪个低点与最小斜率相连,然后记住最佳的那个。
我们可以在 O(log n) 时间内找到最佳连接点,因为它保证位于左侧低点的上凸包上。当我们遍历高点时,我们可以使用单调链算法同时构建其左侧低点的上凸包。这每个点需要摊销常数时间。
给定左侧点的上凸包,我们可以使用二分查找来找到最佳连接点,因为凸包各段的斜率单调递减。对于最佳连接点左侧的所有段,当前最高点将位于其线的下方或线上,而对于最佳连接点右侧的所有段,当前最高点将位于其线的上方或线上。
以下是 Python 中的实现: