LeetCode 3244.新增道路查询后的最短距离 II:贪心(跃迁合并)-9行py(O(n))

【LetMeFly】3244.新增道路查询后的最短距离 II:贪心(跃迁合并)-9行py(O(n))

力扣题目链接:https://leetcode.cn/problems/shortest-distance-after-road-addition-queries-ii/

给你一个整数 n 和一个二维整数数组 queries

n 个城市,编号从 0n - 1。初始时,每个城市 i 都有一条单向 道路通往城市 i + 10 <= i < n - 1)。

queries[i] = [u~i~, v~i~] 表示新建一条从城市 u~i~ 到城市 v~i~ 的单向 道路。每次查询后,你需要找到从城市 0 到城市 n - 1最短路径长度

所有查询中不会存在两个查询都满足 queries[i][0] < queries[j][0] < queries[i][1] < queries[j][1]

返回一个数组 answer,对于范围 [0, queries.length - 1] 中的每个 ianswer[i] 是处理完 i + 1 个查询后,从城市 0 到城市 n - 1 的最短路径的长度

示例 1:
输入: n = 5, queries = [[2, 4], [0, 2], [0, 4]]

输出: [3, 2, 1]

解释:

新增一条从 2 到 4 的道路后,从 0 到 4 的最短路径长度为 3。

新增一条从 0 到 2 的道路后,从 0 到 4 的最短路径长度为 2。

新增一条从 0 到 4 的道路后,从 0 到 4 的最短路径长度为 1。

示例 2:
输入: n = 4, queries = [[0, 3], [0, 2]]

输出: [1, 1]

解释:

新增一条从 0 到 3 的道路后,从 0 到 3 的最短路径长度为 1。

新增一条从 0 到 2 的道路后,从 0 到 3 的最短路径长度仍为 1。

提示:

  • 3 <= n <= 10^5^
  • 1 <= queries.length <= 10^5^
  • queries[i].length == 2
  • 0 <= queries[i][0] < queries[i][1] < n
  • 1 < queries[i][1] - queries[i][0]
  • 查询中不存在重复的道路。
  • 不存在两个查询都满足 i != jqueries[i][0] < queries[j][0] < queries[i][1] < queries[j][1]

解题方法:跃迁合并

把每一条路径视为一条跃迁通道,每个点记录"自己最多能跃迁到的点",初始值每个点能跃迁到的点都是自己的下一个节点。

新来一条"跃迁通道"有两种可能:

  • 被一条更长(或等长)的跃迁通道覆盖
  • 覆盖n条跃迁通道

反正不可能和其他跃迁通道有交叉。

两种情况的判断方式是"跃迁起点"指向的"能跃迁到的点"是否大于(等于)自己的"跃迁终点"

例如新加一条[1, 3]的跃迁路径,结果发现1已经能跃迁到5了,那么就说明这是一条被其他"跃迁通道"覆盖的通道

  • 对于第一种情况:直接continue

  • 对于第二种情况:修改所有"最大被覆盖子跃迁通道"的起点的"能跃迁到的点"

    例如原本有"跃迁通道"[1, 3][3, 4][4, 7],新增"跃迁通道"[1, 7]

    那么就将134的"能跃迁到的点"修改为7

    跃迁次数减少 3 − 1 = 2 3-1=2 3−1=2次

时空复杂度分析

  • 时间复杂度 O ( n + q ) O(n+q) O(n+q):每次修改一个点"能跃迁到的点",总跃迁次数就会减少一;总跃迁次数最多减少到1,说明"跃迁合并"最多 n − 1 n-1 n−1次。
  • 空间复杂度 O ( n ) O(n) O(n),返回值不计入。

AC代码

C++
cpp 复制代码
/*
每个点记录"自己跃迁到的点"
初始值每个点能跃迁到的点都是自己的下一个节点

新来一条"跃迁通道"有两种可能:
    + 被一条更长(或等长)的跃迁通道覆盖
    + 覆盖n条跃迁通道
反正不可能和其他跃迁通道有交叉
两种情况的判断方式是"跃迁起点"指向的"能跃迁到的点"是否大于(等于)自己的"跃迁终点"
    + 对于第一种情况:直接continue
    + 对于第二种情况:修改所有"最大被覆盖子跃迁通道"的起点的"能跃迁到的点"
*/
// FourthTry  // 简化版  // 执行用时分布:2ms,击败98.51%;消耗内存分布:108.84MB,击败83.86%.
class Solution {
public:
    vector<int> shortestDistanceAfterQueries(int n, vector<vector<int>>& queries) {
        vector<int> transitionTo(n), ans(queries.size());
        for (int i = 0; i < n; i++) {
            transitionTo[i] = i + 1;
        }
        int transitionToEndTimes = n - 1;
        for (int i = 0; i < queries.size(); i++) {
            int from = queries[i][0], to = queries[i][1], now = from;
            while (transitionTo[now] < to) {
                transitionToEndTimes--;
                int originalTo = transitionTo[now];
                transitionTo[now] = to;
                now = originalTo;
            }
            ans[i] = transitionToEndTimes;
        }
        return ans;
    }
};
Python
python 复制代码
from typing import List

class Solution:
    def shortestDistanceAfterQueries(self, n: int, queries: List[List[int]]) -> List[int]:
        transitionTo = [i + 1 for i in range(n)]
        ans = []
        shortestTimes = n - 1
        for from_, to in queries:
            while transitionTo[from_] < to:
                shortestTimes -= 1
                transitionTo[from_], from_ = to, transitionTo[from_]
            ans.append(shortestTimes)
        return ans
Java
java 复制代码
class Solution {
    public int[] shortestDistanceAfterQueries(int n, int[][] queries) {
        int[] transitionTo = new int[n];
        for (int i = 0; i < n; i++) {
            transitionTo[i] = i + 1;
        }
        int[] ans = new int[queries.length];
        int minTimes = n - 1;
        for (int i = 0; i < queries.length; i++) {
            int from = queries[i][0], to =  queries[i][1];
            while (transitionTo[from] < to) {
                minTimes--;
                int originalTo = transitionTo[from];
                transitionTo[from] = to;
                from = originalTo;
            }
            ans[i] = minTimes;
        }
        return ans;
    }
}  // AC,100.00%,79.09%
Go
go 复制代码
package main

func shortestDistanceAfterQueries(n int, queries [][]int) (ans []int) {
    transitionTo := make([]int, n)
    for i := range transitionTo {
        transitionTo[i] = i + 1
    }
    minTimes := n - 1
    for _, query := range queries {
        from, to := query[0], query[1]
        for transitionTo[from] < to {
            minTimes--
            transitionTo[from], from = to, transitionTo[from]
        }
        ans = append(ans, minTimes)
    }
    return
}  // AC,81.82%,29.41%

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

Tisfy:https://letmefly.blog.csdn.net/article/details/143908539

相关推荐
星语心愿.27 分钟前
D4——贪心练习
c++·算法·贪心算法
光头man28 分钟前
【八大排序(二)】希尔排序
算法·排序算法
武昌库里写JAVA36 分钟前
使用React Strict DOM改善React生态系统
数据结构·vue.js·spring boot·算法·课程设计
创意锦囊1 小时前
随时随地编码,高效算法学习工具—E时代IDE
ide·学习·算法
stm 学习ing1 小时前
HDLBits训练3
c语言·经验分享·笔记·算法·fpga·eda·verilog hdl
single5941 小时前
【c++笔试强训】(第四十一篇)
java·c++·算法·深度优先·图论·牛客
yuanbenshidiaos1 小时前
C++-----函数与库
开发语言·c++·算法
清弦墨客1 小时前
【数据结构与算法】深度优先搜索:树与图的路径探寻之道
数据结构·python·算法·蓝桥杯·深度优先
尘觉1 小时前
算法的学习笔记—扑克牌顺子(牛客JZ61)
数据结构·笔记·学习·算法
1 9 J1 小时前
Java 上机实践11(组件及事件处理)
java·开发语言·学习·算法