1266. 访问所有点的最小时间

本文介绍了一道LeetCode题目,涉及如何在二维平面上按最优路径访问n个给定点,通过计算切比雪夫距离并结合移动规则求解。作者提供了Java代码实现,展示了如何使用minTimeToVisitAllPoints方法计算最小时间。
package com.heu.wsq.leetcode.arr;

/**
 * 1266. 访问所有点的最小时间
 * @author wsq
 * @date 2021/1/15
 * 平面上有 n 个点,点的位置用整数坐标表示 points[i] = [xi, yi]。请你计算访问所有这些点需要的最小时间(以秒为单位)。
 * 你可以按照下面的规则在平面上移动:
 * 每一秒沿水平或者竖直方向移动一个单位长度,或者跨过对角线(可以看作在一秒内向水平和竖直方向各移动一个单位长度)。
 * 必须按照数组中出现的顺序来访问这些点。
 *
 *  输入:points = [[1,1],[3,4],[-1,0]]
 * 输出:7
 * 解释:一条最佳的访问路径是: [1,1] -> [2,2] -> [3,3] -> [3,4] -> [2,3] -> [1,2] -> [0,1] -> [-1,0]
 * 从 [1,1] 到 [3,4] 需要 3 秒
 * 从 [3,4] 到 [-1,0] 需要 4 秒
 * 一共需要 7 秒
 *
 * 链接:https://leetcode-cn.com/problems/minimum-time-visiting-all-points
 */
public class MinTimeToVisitAllPoints {
    /**
     * 切比雪夫距离
     * dx = abs(x0 - x1)
     * dy = abs(y0 - y1)
     * d = max(dx, dy)
     * @param points
     * @return
     */
    public int minTimeToVisitAllPoints(int[][] points){
        int n = points.length;
        int ans = 0;
        for (int i = 1; i < n; i++){
            int[] prePoint = points[i - 1];
            int[] currPoint = points[i];
            int dx = Math.abs(prePoint[0] - currPoint[0]);
            int dy = Math.abs(prePoint[1] - currPoint[1]);
            ans += Math.max(dx, dy);
        }
        return ans;
    }
}

### 最小堆的时间复杂度分析 最小堆是一种特殊的完全二叉树,其中每个父节的键值都小于或等于其子节的键值。它通常用于高效地获取集合中的最小元素,在许多应用场景中非常有用,比如优先队列、堆排序以及查找前 K 小的元素。 #### 1. 插入操作的时间复杂度 当向最小堆中插入一个新元素时,需要将其放置到堆的最后一层最后一个位置,并通过向上调整(`up-heap` 或 `bubble-up`)来恢复堆的性质。这个过程中,每次比较和交换都会沿着从叶子节到根节的方向进行,最多可能经过树的高度次操作。由于完全二叉树的高度为 \( O(\log n) \),因此单次插入操作的时间复杂度为 \( O(\log n) \)[^3]。 #### 2. 删除最小元素的操作时间复杂度 删除最小堆中的最小元素(通常是根节)后,需要用堆中最后的一个元素替代根节的位置,并执行向下调整(`down-heap` 或 `sink-down`)。这一过程会沿着从根节到叶节的方向逐步比较并交换,同样最多涉及树的高度次操作。因此,删除最小元素的时间复杂度也为 \( O(\log n) \)[^4]。 #### 3. 构建堆的时间复杂度 构建一个大小为 \( n \) 的最小堆可以通过自底向上的方式完成,即将每一个非叶子节依次调用 `down-heap` 操作。尽管每一步单独来看可能是 \( O(h) \) (\( h \) 是当前节的高度),但由于较低层次的节数量更多,整体复杂度并非简单的累加而是更接近于线性级别。具体来说,构建整个堆的过程可以在 \( O(n) \) 时间内完成[^1]。 #### 4. 查找最小元素的时间复杂度 在最小堆中找到最小元素是非常高效的,因为最小元素始终位于堆的顶部(即数组的第一个元素)。因此,查找最小元素只需要常数级别的访问即可实现,时间复杂度为 \( O(1) \)[^5]。 --- ### 示例代码:Python 实现最小堆的部分功能 以下是基于 Python 编写的简单版本最小堆部分核心方法: ```python class MinHeap: def __init__(self, capacity): self.heap = [] self.capacity = capacity def insert(self, value): if len(self.heap) >= self.capacity: return False self.heap.append(value) self._sift_up(len(self.heap)-1) def extract_min(self): if not self.heap: return None min_val = self.heap[0] last_value = self.heap.pop() if self.heap: self.heap[0] = last_value self._sift_down(0) return min_val def _parent(self, index): return (index - 1) // 2 def _left_child(self, index): return 2 * index + 1 def _right_child(self, index): return 2 * index + 2 def _sift_up(self, index): parent_index = self._parent(index) while index > 0 and self.heap[parent_index] > self.heap[index]: self.heap[parent_index], self.heap[index] = self.heap[index], self.heap[parent_index] index = parent_index parent_index = self._parent(index) def _sift_down(self, index): size = len(self.heap) min_index = index l = self._left_child(index) if l < size and self.heap[l] < self.heap[min_index]: min_index = l r = self._right_child(index) if r < size and self.heap[r] < self.heap[min_index]: min_index = r if index != min_index: self.heap[index], self.heap[min_index] = self.heap[min_index], self.heap[index] self._sift_down(min_index) ``` ---
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值