算法题:通往目的地的连接道路

发布于 2023-07-18 09:38:15 字数 4981 浏览 34 评论 0

题目描述

You are given integers sx, sy, ex, ey and two-dimensional list of integers roads. You are currently located at coordinate (sx, sy) and want to move to destination (ex, ey). Each element in roads contains (x, y) which is a road that will be added at that coordinate. Roads are added one by one in order. You can only move to adjacent (up, down, left, right) coordinates if there is a road in that coordinate or if it's the destination coordinate. For example, at (x, y) we can move to (x + 1, y) if (x + 1, y) is a road or the destination.

Return the minimum number of roads in order that must be added before there is a path consisting of roads that allows us to get to (ex, ey) from (sx, sy). If there is no solution, return -1.

Constraints

0 ≤ n ≤ 100,000 where n is the length of roads
Example 1
Input
sx = 0
sy = 0
ex = 1
ey = 2
roads = [
    [9, 9],
    [0, 1],
    [0, 2],
    [0, 3],
    [3, 3]
]
Output
3
Explanation
We need to add the first three roads which allows us to go from (0, 0), (0, 1), (0, 2), (1, 2). Note that we must take (9, 9) since roads must be added in order.

题目地址

https://binarysearch.com/problems/Connected-Road-to-Destination

前置知识

  • 二分
  • 并查集

二分(超时)

本质就是能力检测二分。关于能力检测二分,我在我的二分专题已经做了详细的介绍,不再赘述。

因为我们我们只需要在 [0, len(roads)] 值域内做能力检测即可,然后根据检测结果二分值域。由于是求最小的满足起点和终点联通的铺设道路的数量,因此使用最左二分即可。

这里我套用了最左二分的模板。 问题的关键是能力检测如何写?这里的能力检测本质是检测在给的前 x 个 roads,问起点和终点是否联通

不妨使用 BFS, 从 起点开始搜索,如果存在一条通路到终点,那么返回存在即可。要搜索就需要构建图,构图的关键是构建边。这道题的边其实就是点的上下左右邻居,不过邻居要在 roads 中存在才行哦,这点需要注意。据此,不难写出如下代码。

思路

代码

class Solution:
    def solve(self, sx, sy, ex, ey, roads):
        def possible(mid):
            dic = set([(sx, sy), (ex, ey)])
            visited = set()
            q = collections.deque([(sx, sy)])
            for x, y in roads[:mid]:
                dic.add((x, y))
            while q:
                x, y = q.popleft()
                if (x, y) in visited: continue
                visited.add((x, y))
                if (x, y) == (ex, ey): return True
                for dx, dy in [(1,0),(-1,0), (0,1), (0,-1)]:
                    if (x + dx, y + dy) in dic:
                        q.append((x + dx, y + dy))
            return False
        l, r = 0, len(roads)

        while l <= r:
            mid = (l + r) // 2
            if possible(mid):
                r = mid - 1
            else:
                l = mid + 1
        return -1 if l > len(roads) else l

复杂度分析

令 n 为 roads 的长度。

  • 时间复杂度:$O(nlogn)$,logn 用于二分,n 用于能力检测。
  • 空间复杂度:$O(n)$

并查集

思路

上面我不停地提起联通 这个词。这提示我们使用并查集来完成。

从起点不断加边,直到起点和终点联通或者 roads 加入完了。同样,可以使用我的并查集专题的模板。

由于需要加边,因此对模板需要进行一点小小调整,增加 add(x) api 用于加点,功能是将 x 加入到图中,接下来使用 union 加边即可。

代码

代码支持:Python3

Python Code:


class UF:
  def __init__(self):
      self.parent = {}
      self.cnt = 0
  def add(self, i):
      self.parent[i] = i
      self.cnt += 1

  def find(self, x):
      if x != self.parent[x]:
          self.parent[x] = self.find(self.parent[x])
          return self.parent[x]
      return x
  def union(self, p, q):
      if p not in self.parent or q not in self.parent: return
      if self.connected(p, q): return
      leader_p = self.find(p)
      leader_q = self.find(q)
      self.parent[leader_p] = leader_q
      self.cnt -= 1
  def connected(self, p, q):
      return self.find(p) == self.find(q)

class Solution:
    def solve(self, sx, sy, ex, ey, roads):
        start = (sx, sy)
        end = (ex, ey)
        # 注意特判
        for dx, dy in [(0, 0), (1,0), (-1,0), (0,1), (0,-1)]:
            x = sx + dx
            y = sy + dy
            if (x, y) == (ex, ey): return 0

        uf = UF()
        uf.add(start)
        uf.add(end)

        for i, road in enumerate(map(tuple, roads)):
            uf.add(road)
            for dx, dy in [(1,0), (-1,0), (0,1), (0,-1)]:
                x = road[0] + dx
                y = road[1] + dy
                uf.union(road, (x, y))
                if uf.connected(start, end):
                    return i + 1

        return -1

复杂度分析

令 n 为 roads 的长度。

  • 时间复杂度:$O(n)$
  • 空间复杂度:$O(n)$

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

归途

暂无简介

文章
评论
562 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文