1266. Minimum Time Visiting All Points*

1266. Minimum Time Visiting All Points*

https://leetcode.com/problems/minimum-time-visiting-all-points/

题目描述

On a plane there are n points with integer coordinates points[i] = [xi, yi]. Your task is to find the minimum time in seconds to visit all points.

You can move according to the next rules:

In one second always you can either move vertically, horizontally by one unit or diagonally (it means to move one unit vertically and one unit horizontally in one second).
You have to visit the points in the same order as they appear in the array.

Input: points = [[1,1],[3,4],[-1,0]]
Output: 7
Explanation: One optimal path is [1,1] -> [2,2] -> [3,3] -> [3,4] -> [2,3] -> [1,2] -> [0,1] -> [-1,0]   
Time from [1,1] to [3,4] = 3 seconds 
Time from [3,4] to [-1,0] = 4 seconds
Total time = 7 seconds

Example 2:

Input: points = [[3,2],[-2,2]]
Output: 5

Constraints:

points.length == n
1 <= n <= 100
points[i].length == 2
-1000 <= points[i][0], points[i][1] <= 1000

解题思路

这道题标注为 Easy, 但是要愉快的求解, 还是需要细细观察, 发现规律. 首先注意题目的要求:

  1. 移动时能左右, 上下以及对角移动
  2. 移动的顺序和点在数组中出现的顺序相同.
    基于以上的要求, 可以将问题简化成 “如何用最少的步数从 A 点达到 B 点(或者 D 点)”, 如下图:

如上图, 先看 A 如何以最小步数移动到 B. 首先可以分别通过 A 和 B 画两条斜线, 用来显示按斜线方向移动的轨迹. 可以发现, 按照路线 A -> a1 -> B 移动, 步数是最少的, 另外还可以观察到的一点是, 按这个路线移动使用的步数刚好等于 BC 的长度, 这是因为 A -> a1 的步数与 C -> a1 的步数是相同的. 从这里我们可以得到一个结论:

  • BF 上的任意一点, 假设为 K, 坐标设置为 ( x K , y K ) (x_K, y_K) (xK,yK), 从 A (假设坐标设置为 ( x A , y A ) (x_A, y_A) (xA,yA)) 移动到 K 的最小步数刚好等于 abs ( y K − y A ) \text{abs}(y_K - y_A) abs(yKyA);

下面再来看 A 是如何以最小的步数移动到 D 的. 首先仍然是通过 A 和 D 画两条斜线, 可以发现, 按照路线 A -> c1 -> D 移动, 所用的步数最少. 另外还可以观察到的一点是, 按照这个路线移动的步数刚好等于 AE 的长度, 这是因为 c1 -> D 的步数和 c1 -> E 的步数是相同的. 从这里我们可以得到第二个结论:

  • DF 上移动的任意一点, 假设为 K, 坐标设置为 ( x K , y K ) (x_K, y_K) (xK,yK), 从 A (假设坐标设置为 ( x A , y A ) (x_A, y_A) (xA,yA)) 移动到 K 的最小步数刚好等于 abs ( x K − x A ) \text{abs}(x_K - x_A) abs(xKxA).

于是剩下的问题是, 如何判断第二个点的位置是在 B 处还是在 D 处. 方法很简单, 如果在 B 处, 那么总会满足条件 BC > AC; 而如果在 D 处, 那么总会有 AE > DE. 而 BC 刚好是 A -> B 的最小步数, AE 刚好是 A -> D 的最小步数.
翻译过来就是我们只需要比较两个点的横坐标之差与纵坐标之差哪个更大即可求出最小步数:

min_step = std::max(std::abs(A[0] - B[0]), std::abs(A[1] - B[1]));

完整实现代码如下.

C++ 实现 1

了解上一节的原理之后, 代码就很好写了. 引入一个辅助函数 time 来记录两点之间移动所需要的最小步数, 之后统计访问数组中所有点所需要的最小时间.

class Solution {
private:
    int time(const vector<int> &p1, const vector<int> &p2) {
        if (p1.empty() || p2.empty()) return 0;
        return std::max(std::abs(p2[0] - p1[0]), std::abs(p2[1] - p1[1]));
    }
public:
    int minTimeToVisitAllPoints(vector<vector<int>>& points) {
        if (points.size() < 2) return 0;
        int min_time = 0;
        for (int i = 1; i < points.size(); ++ i)
            min_time += time(points[i - 1], points[i]);    
        return min_time;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值