Leetcode 3464. Maximize the Distance Between Points on a Square

1. 解题思路

说来惭愧,这道题我也没有自力搞定,也是问了一下DeepSeek R1之后搞明白的解法,感觉真的被LLM完爆了……

不过,也不知道是不是错觉,总觉得DeepSeek发布之后,Leetcode每周hard的题目都变得难了好多,以前基本都能搞定,最近感觉卡壳的几率好高……

这道题核心思路还是二分法求临界值,因此我们事实上要做的就是在已知目标距离 d d d的情况下判断能否从给定的 n n n个点当中找出 k k k个点,使得其两两的曼哈顿距离的最小值均不小于 d d d

然后我就卡在这里了,完全没啥好的思路,但是DeepSeek R1搞定了。

它的思路的话其实还是挺简单的,就是先将所有的点的坐标改写为一个标量值然后进行排列,并确保任意两个点之间的曼哈顿距离就是这两个标量的差,由此,我们即可以通过二分法快速地查找得到当一个点被取用是其下一个可取用的点,且保证该取法下任意两个点之间的距离均不小于 d d d

但这里的问题就在于说如何进行这个排序的过程,DeepSeek给出的方法是使用周长的方式,即从坐标点 ( 0 , 0 ) (0,0) (0,0)开始顺时针延正方形绕一圈,任意点的坐标就是其到原点 ( 0 , 0 ) (0, 0) (0,0)的距离。

需要注意的是,在这种情况下,上述描述,即任意两点的曼哈顿距离就是其坐标的差这个表述事实上并不总是满足,当两个点分别位于平行的两条对边上时是不成立的,但是因为 k ≥ 4 k \geq 4 k4,因此事实上我们的距离上限总是小于等于边长 s s s的,因此我们事实上只需要保证临边上的两点的距离计算正确即可,而这是可以保证的。

另外还要注意的是,考察靠后的点作为第一个取用的点时,我们需要回过头来考察头部点,因此我们需要绕两圈来成环,且需要保证我们最终取出来的 k k k个点的跨度在 4 s − d 4s-d 4sd范围内,不然最后两个点的距离同样会小于 d d d

2. 代码实现

给出最终的python代码实现如下:

class Solution:
    def maxDistance(self, side: int, points: List[List[int]], k: int) -> int:
            # 转换每个点到周长坐标
            sorted_p = []
            for x, y in points:
                if x == 0:
                    coord = y
                elif y == side:
                    coord = side + x
                elif x == side:
                    coord = 3 * side - y
                else:  # y == 0
                    coord = 3 * side + (side - x)
                sorted_p.append(coord)
            sorted_p.sort()
            n = len(sorted_p)

            def is_possible(d):
                if d == 0:
                    return True
                # 扩展数组以处理环形问题
                extended_p = sorted_p + [p + 4 * side for p in sorted_p]
                # 遍历每个可能的起点
                for i in range(n):
                    current = i
                    count = 1
                    for _ in range(k - 1):
                        target = extended_p[current] + d
                        # 查找下一个点的位置
                        j = bisect.bisect_left(extended_p, target, current + 1)
                        if j >= len(extended_p):
                            break
                        current = j
                        count += 1
                    if count >= k:
                        # 计算跨度
                        span = extended_p[current] - extended_p[i]
                        if span <= 4 * side - d:
                            return True
                return False

            # 二分查找
            low = 0
            high = side + 1
            ans = 0
            while low < high-1:
                mid = (low + high) // 2
                if is_possible(mid):
                    low = mid
                else:
                    high = mid
            return low

提交代码评测得到:耗时739ms,占用内存23.4MB。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值