当前位置: 首页 > news >正文

Kimi LeetCode 3464. 正方形上的点之间的最大距离 Python3实现

LeetCode 3464. 正方形上的点之间的最大距离 — Python3 实现

题目概述

给定正方形边长 `side`,以及位于正方形边界上的若干点。需要从中选出 `k` 个点,使得任意两点之间的最小曼哈顿距离最大化。

- 曼哈顿距离:`|x1 - x2| + |y1 - y2|`
- 关键约束:`k <= 25`,`points.length <= 15000`

核心思路

这是一个经典的 "最大化最小值" 问题,标准解法是二分答案 + 可行性检验。

关键观察

1. 答案上界为 `side`:因为 `k >= 4`,至少有两个点在同一条边上或相邻边上,而同一/相邻边上的点距离最大为 `side`(当 `k=4` 时选四个角,最小距离恰好为 `side`)。

2. 展开为正方形周长:将正方形边界展开为一维环形数组(周长 `4 * side`),按顺时针顺序排列所有点。这样相邻点之间的距离可以用曼哈顿距离表示。

展开映射规则:
- 左边 `x=0`:`d = y`
- 上边 `y=side`:`d = side + x`
- 右边 `x=side`:`d = 3 * side - y`
- 下边 `y=0`:`d = 4 * side - x`

3. 可行性检验:对于候选距离 `limit`,检查是否能选出 `k` 个点,使得相邻点(包括首尾环绕)的曼哈顿距离都 `>= limit`。由于 `k <= 25`,可以枚举每个点作为起点,贪心选择下一个满足距离要求的点。

Python3 实现

```python
import bisect
from typing import List

class Solution:
def maxDistance(self, side: int, points: List[List[int]], k: int) -> int:
"""
二分答案 + 贪心可行性检验
将正方形边界展开为一维环形数组
"""
n = len(points)
positions = []

# 将边界点展开为一维坐标(顺时针方向)
for x, y in points:
if x == 0:
# 左边:从 (0,0) 向上到 (0, side)
d = y
elif y == side:
# 上边:从 (0, side) 向右到 (side, side)
d = side + x
elif x == side:
# 右边:从 (side, side) 向下到 (side, 0)
d = 3 * side - y
else:
# 下边:从 (side, 0) 向左到 (0, 0)
d = 4 * side - x
positions.append(d)

positions.sort()
perimeter = 4 * side

def can_pick(limit: int) -> bool:
"""
检查是否能选出 k 个点,相邻点距离 >= limit(包括首尾环绕)
"""
# 枚举每个点作为起点
for start_idx in range(n):
start = positions[start_idx]
# 最后一个点不能超过 start + perimeter - limit(保证首尾环绕距离 >= limit)
last_allowed = start + perimeter - limit
current = start
picked = 1

for _ in range(k - 1):
# 找下一个 >= current + limit 的点
next_idx = bisect.bisect_left(positions, current + limit)

# 如果超出数组范围,或者超出 last_allowed,则失败
if next_idx >= n or positions[next_idx] > last_allowed:
break

current = positions[next_idx]
picked += 1
else:
# 成功选了 k 个点
return True

return False

# 二分搜索答案 [1, side]
left, right = 1, side
ans = 0

while left <= right:
mid = (left + right) // 2
if can_pick(mid):
ans = mid
left = mid + 1
else:
right = mid - 1

return ans
```

复杂度分析

- 时间复杂度:`O(n log n + n * k * log n * log side)`
- 排序:`O(n log n)`
- 二分答案:`O(log side)` 次
- 每次检验:枚举 `n` 个起点,每个起点贪心选 `k` 个点,每次用二分查找 `O(log n)`
- 由于 `k <= 25`,实际运行很快

- 空间复杂度:`O(n)`

示例验证

输入 输出 说明
`side=2, points=[[0,2],[2,0],[2,2],[0,0]], k=4` `2` 四个角,最小距离为 2
`side=2, points=[[0,0],[1,2],[2,0],[2,2],[2,1]], k=4` `1` 选 (0,0), (2,0), (2,2), (2,1)
`side=2, points=[[0,0],[0,1],[0,2],[1,2],[2,0],[2,2],[2,1]], k=5` `1` 选 (0,0), (0,1), (0,2), (1,2), (2,2)

注意事项

上述实现基于 展开+贪心 的经典方法。但需要注意:在展开为一维坐标后,相邻边的点之间的曼哈顿距离与一维距离的关系需要仔细处理。对于 `limit <= side` 的情况,展开方法能正确工作,因为:
- 同一边上的点:一维距离 = 曼哈顿距离
- 相邻边上的点:一维距离 = 曼哈顿距离
- 对边上的点:曼哈顿距离 >= side >= limit,不会成为瓶颈

如果追求更严谨的实现,可以参考使用 双端队列 DP 的方法(如搜索结果中的 `Sequence` 类实现),它直接在二维坐标上用滑动窗口维护最长合法子序列。

http://www.cnnetsun.cn/news/3161654.html

相关文章:

  • 深度学习项目复现实战:从GitHub代码到可运行结果的系统方法论
  • 35B Agent超越万亿参数模型?上海AI Lab开源Agents-A1:scaling the Horizon
  • python语法竟如此简单,str append用法你知道吗?
  • 《图片添加贴纸》四、PhotoViewPicker使用指南
  • 3PEAK思瑞浦 LM339-SO2R SOP14 比较器
  • 山东大学软件学院 2026 年数据库系统期末考试回忆版
  • Burp Suite入门指南:从零掌握Web抓包与安全测试核心功能
  • 多模型统一接入实战:Agent 开发如何用一套 API 搞定 DeepSeek、Qwen、GLM、Llama?
  • redis的aof方式恢复
  • Java安全管理器实战:从零构建OJ判题机安全沙箱
  • Windows EFS加密文件重装系统后恢复全攻略:原理、场景与实操
  • 抖音无水印视频下载终极指南:三步搞定批量下载难题
  • 影刀RPA新手教程:Python协同入门完全指南——不会Python也能在影刀里用Python
  • AI攻防时代:智能风控如何应对自动化攻击新范式
  • 标称网格的地理经纬度
  • HCI 功能规范【4.8. Versioned events】
  • 总目录 2026版国家级全领域科研痛点攻关
  • 第25篇:数据安全:从“边界防护”到“纵深防御”
  • 关于C++多重继承下虚表结构的问题
  • Redis分布式锁进阶第三十七篇
  • 奇迹 MU 剑与翼手游官网下载:奇迹 MU 剑与翼最新官方下载渠道
  • SRC漏洞挖掘入门:8种实战姿势与零基础进阶路径
  • Three.js 城市光影教程
  • 数学的本质是什么?——数学为什么如此不可思议地有效-龍德明宇
  • 主动推理-信息组织
  • SpringBoot3.x新特性解读与迁移指南
  • 影刀RPA深度教程:异常处理与调试完全指南
  • 泳池设备品牌哪家好
  • 《欠你的那场婚礼》 台剧|在线观看|电视剧|夸克|下载|豆瓣
  • 嵌入式系统2x2矩阵键盘设计与74HC32应用