普通视图

发现新文章,点击刷新页面。
今天 — 2026年1月12日技术

每日一题-访问所有点的最小时间🟢

2026年1月12日 00:00

平面上有 n 个点,点的位置用整数坐标表示 points[i] = [xi, yi] 。请你计算访问所有这些点需要的 最小时间(以秒为单位)。

你需要按照下面的规则在平面上移动:

  • 每一秒内,你可以:
    • 沿水平方向移动一个单位长度,或者
    • 沿竖直方向移动一个单位长度,或者
    • 跨过对角线移动 sqrt(2) 个单位长度(可以看作在一秒内向水平和竖直方向各移动一个单位长度)。
  • 必须按照数组中出现的顺序来访问这些点。
  • 在访问某个点时,可以经过该点后面出现的点,但经过的那些点不算作有效访问。

 

示例 1:

输入: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 秒

示例 2:

输入:points = [[3,2],[-2,2]]
输出:5

 

提示:

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

切比雪夫距离(Python/Java/C++/C/Go/JS/Rust)

作者 endlesscheng
2025年12月31日 13:57

假设我们要从点 $(x_1,y_1)$ 移动到点 $(x_2,y_2)$。

水平距离为 $d_x = |x_1-x_2|$。

垂直距离为 $d_y = |y_1-y_2|$。

如果 $d_x$ 和 $d_y$ 都大于 $0$,那么:

  • 使用对角线移动,一秒就能把 $d_x$ 和 $d_y$ 都减少 $1$。
  • 另外两种移动,一秒只能把 $d_x$ 和 $d_y$ 的其中一个减少一。

所以当 $d_x$ 和 $d_y$ 都大于 $0$ 时,使用对角线移动是最优的。

  • 如果 $d_x > d_y$,先沿着对角线移动 $d_y$ 秒,再水平移动 $d_x - d_y$ 秒,一共移动 $d_x$ 秒。
  • 如果 $d_x \le d_y$,先沿着对角线移动 $d_x$ 秒,再垂直移动 $d_y - d_x$ 秒,一共移动 $d_y$ 秒。

所以从点 $(x_1,y_1)$ 移动到点 $(x_2,y_2)$ 至少要花

$$
\max(d_x,d_y) = \max(|x_1-x_2|,|y_1-y_2|)
$$

秒。上式也是两点的切比雪夫距离。

由于题目要求「必须按照数组中出现的顺序来访问这些点」,我们遍历 $\textit{points}$ 中的相邻点对,计算上式,累加即为答案。

###py

class Solution:
    def minTimeToVisitAllPoints(self, points: List[List[int]]) -> int:
        ans = 0
        for (x1, y1), (x2, y2) in pairwise(points):
            ans += max(abs(x1 - x2), abs(y1 - y2))
        return ans

###py

class Solution:
    def minTimeToVisitAllPoints(self, points: List[List[int]]) -> int:
        return sum(max(abs(x1 - x2), abs(y1 - y2)) for (x1, y1), (x2, y2) in pairwise(points))

###java

class Solution {
    public int minTimeToVisitAllPoints(int[][] points) {
        int ans = 0;
        for (int i = 1; i < points.length; i++) {
            int[] p = points[i - 1];
            int[] q = points[i];
            ans += Math.max(Math.abs(p[0] - q[0]), Math.abs(p[1] - q[1]));
        }
        return ans;
    }
}

###cpp

class Solution {
public:
    int minTimeToVisitAllPoints(vector<vector<int>>& points) {
        int ans = 0;
        for (int i = 1; i < points.size(); i++) {
            auto& p = points[i - 1];
            auto& q = points[i];
            ans += max(abs(p[0] - q[0]), abs(p[1] - q[1]));
        }
        return ans;
    }
};

###c

#define MAX(a, b) ((b) > (a) ? (b) : (a))

int minTimeToVisitAllPoints(int** points, int pointsSize, int* pointsColSize) {
    int ans = 0;
    for (int i = 1; i < pointsSize; i++) {
        int* p = points[i - 1];
        int* q = points[i];
        ans += MAX(abs(p[0] - q[0]), abs(p[1] - q[1]));
    }
    return ans;
}

###go

func minTimeToVisitAllPoints(points [][]int) (ans int) {
for i := 1; i < len(points); i++ {
p := points[i-1]
q := points[i]
ans += max(abs(p[0]-q[0]), abs(p[1]-q[1]))
}
return
}

func abs(x int) int {
if x < 0 {
return -x
}
return x
}

###js

var minTimeToVisitAllPoints = function(points) {
    let ans = 0;
    for (let i = 1; i < points.length; i++) {
        const [x1, y1] = points[i - 1];
        const [x2, y2] = points[i];
        ans += Math.max(Math.abs(x1 - x2), Math.abs(y1 - y2));
    }
    return ans;
};

###rust

impl Solution {
    pub fn min_time_to_visit_all_points(points: Vec<Vec<i32>>) -> i32 {
        points.windows(2)
            .map(|w| (w[0][0] - w[1][0]).abs().max((w[0][1] - w[1][1]).abs()))
            .sum()
    }
}

复杂度分析

  • 时间复杂度:$\mathcal{O}(n)$,其中 $n$ 是 $\textit{points}$ 的长度。
  • 空间复杂度:$\mathcal{O}(1)$。

分类题单

如何科学刷题?

  1. 滑动窗口与双指针(定长/不定长/单序列/双序列/三指针/分组循环)
  2. 二分算法(二分答案/最小化最大值/最大化最小值/第K小)
  3. 单调栈(基础/矩形面积/贡献法/最小字典序)
  4. 网格图(DFS/BFS/综合应用)
  5. 位运算(基础/性质/拆位/试填/恒等式/思维)
  6. 图论算法(DFS/BFS/拓扑排序/基环树/最短路/最小生成树/网络流)
  7. 动态规划(入门/背包/划分/状态机/区间/状压/数位/数据结构优化/树形/博弈/概率期望)
  8. 常用数据结构(前缀和/差分/栈/队列/堆/字典树/并查集/树状数组/线段树)
  9. 数学算法(数论/组合/概率期望/博弈/计算几何/随机算法)
  10. 贪心与思维(基本贪心策略/反悔/区间/字典序/数学/思维/脑筋急转弯/构造)
  11. 链表、树与回溯(前后指针/快慢指针/DFS/BFS/直径/LCA)
  12. 字符串(KMP/Z函数/Manacher/字符串哈希/AC自动机/后缀数组/子序列自动机)

我的题解精选(已分类)

访问所有点的最小时间

2020年2月19日 11:34

方法一:切比雪夫距离

对于平面上的两个点 x = (x0, x1)y = (y0, y1),设它们横坐标距离之差为 dx = |x0 - y0|,纵坐标距离之差为 dy = |x1 - y1|,对于以下三种情况,我们可以分别计算出从 x 移动到 y 的最少次数:

  • dx < dy:沿对角线移动 dx 次,再竖直移动 dy - dx 次,总计 dx + (dy - dx) = dy 次;

  • dx == dy:沿对角线移动 dx 次;

  • dx > dy:沿对角线移动 dy 次,再水平移动 dx - dy 次,总计 dy + (dx - dy) = dx 次。

可以发现,对于任意一种情况,从 x 移动到 y 的最少次数为 dxdy 中的较大值 max(dx, dy),这也被称作 xy 之间的 切比雪夫距离

由于题目要求,需要按照数组中出现的顺序来访问这些点。因此我们遍历整个数组,对于数组中的相邻两个点,计算出它们的切比雪夫距离,所有的距离之和即为答案。

###C++

class Solution {
public:
    int minTimeToVisitAllPoints(vector<vector<int>>& points) {
        int x0 = points[0][0], x1 = points[0][1];
        int ans = 0;
        for (int i = 1; i < points.size(); ++i) {
            int y0 = points[i][0], y1 = points[i][1];
            ans += max(abs(x0 - y0), abs(x1 - y1));
            x0 = y0;
            x1 = y1;
        }
        return ans;
    }
};

###Python

class Solution:
    def minTimeToVisitAllPoints(self, points: List[List[int]]) -> int:
        x0, x1 = points[0]
        ans = 0
        for i in range(1, len(points)):
            y0, y1 = points[i]
            ans += max(abs(x0 - y0), abs(x1 - y1))
            x0, x1 = points[i]
        return ans

###Java

class Solution {
    public int minTimeToVisitAllPoints(int[][] points) {
        int x0 = points[0][0], y0 = points[0][1];
        int ans = 0;
        for (int i = 1; i < points.length; ++i) {
            int x1 = points[i][0], y1 = points[i][1];
            ans += Math.max(Math.abs(x0 - x1), Math.abs(y0 - y1));
            x0 = x1;
            y0 = y1;
        }
        return ans;
    }
}

###C#

public class Solution {
    public int MinTimeToVisitAllPoints(int[][] points) {
        int x0 = points[0][0], y0 = points[0][1];
        int ans = 0;
        for (int i = 1; i < points.Length; ++i) {
            int x1 = points[i][0], y1 = points[i][1];
            ans += Math.Max(Math.Abs(x0 - x1), Math.Abs(y0 - y1));
            x0 = x1;
            y0 = y1;
        }
        return ans;
    }
}

###Go

func minTimeToVisitAllPoints(points [][]int) int {
    x0, y0 := points[0][0], points[0][1]
    ans := 0
    for i := 1; i < len(points); i++ {
        x1, y1 := points[i][0], points[i][1]
        dx := abs(x0 - x1)
        dy := abs(y0 - y1)
        if dx > dy {
            ans += dx
        } else {
            ans += dy
        }
        x0, y0 = x1, y1
    }
    return ans
}

func abs(x int) int {
    if x < 0 {
        return -x
    }
    return x
}

###C

#include <stdlib.h>

int minTimeToVisitAllPoints(int** points, int pointsSize, int* pointsColSize) {
    int x0 = points[0][0], y0 = points[0][1];
    int ans = 0;
    for (int i = 1; i < pointsSize; ++i) {
        int x1 = points[i][0], y1 = points[i][1];
        int dx = abs(x0 - x1);
        int dy = abs(y0 - y1);
        ans += (dx > dy) ? dx : dy;
        x0 = x1;
        y0 = y1;
    }
    return ans;
}

###JavaScript

var minTimeToVisitAllPoints = function(points) {
    let x0 = points[0][0], y0 = points[0][1];
    let ans = 0;
    for (let i = 1; i < points.length; ++i) {
        let x1 = points[i][0], y1 = points[i][1];
        ans += Math.max(Math.abs(x0 - x1), Math.abs(y0 - y1));
        x0 = x1;
        y0 = y1;
    }
    return ans;
};

###TypeScript

function minTimeToVisitAllPoints(points: number[][]): number {
    let x0 = points[0][0], y0 = points[0][1];
    let ans = 0;
    for (let i = 1; i < points.length; ++i) {
        let x1 = points[i][0], y1 = points[i][1];
        ans += Math.max(Math.abs(x0 - x1), Math.abs(y0 - y1));
        x0 = x1;
        y0 = y1;
    }
    return ans;
}

###Rust

impl Solution {
    pub fn min_time_to_visit_all_points(points: Vec<Vec<i32>>) -> i32 {
        let mut x0 = points[0][0];
        let mut y0 = points[0][1];
        let mut ans = 0;
        
        for i in 1..points.len() {
            let x1 = points[i][0];
            let y1 = points[i][1];
            ans += (x0 - x1).abs().max((y0 - y1).abs());
            x0 = x1;
            y0 = y1;
        }
        
        ans
    }
}

复杂度分析

  • 时间复杂度:$O(N)$,其中 $N$ 是数组的长度。

  • 空间复杂度:$O(1)$。

C++:暴力法

作者 yfnupup
2019年11月24日 12:31

题解:两点之间的距离就是直角三角形直角边的较大值

image.png

代码如下:

###cpp

class Solution {
public:
    int minTimeToVisitAllPoints(vector<vector<int>>& points) {
        int step=0;
        for(int i=0;i<points.size()-1;++i)
        {
            int x=abs(points[i][0]-points[i+1][0]);
            int y=abs(points[i][1]-points[i+1][1]);
            step+=max(x,y);
        }
        return step;
    }  
};
昨天 — 2026年1月11日技术
❌
❌