Problem Statement

In a 1 million by 1 million grid, the coordinates of each grid square are (x, y) with 0 <= x, y < 10^6.

We start at the source square and want to reach the target square.  Each move, we can walk to a 4-directionally adjacent square in the grid that isn't in the given list of blocked squares.

Return true if and only if it is possible to reach the target square through a sequence of moves.

Example 1:

Input: blocked = [[0,1],[1,0]], source = [0,0], target = [0,2]
Output: false
Explanation:
The target square is inaccessible starting from the source square, because we can't walk outside the grid.

Example 2:

Input: blocked = [], source = [0,0], target = [999999,999999]
Output: true
Explanation:
Because there are no blocked cells, it's possible to reach the target square.

Note:

  1. 0 <= blocked.length <= 200
  2. blocked[i].length == 2
  3. 0 <= blocked[i][j] < 10^6
  4. source.length == target.length == 2
  5. 0 <= source[i][j], target[i][j] < 10^6
  6. source != target

Hints

  • If we become stuck, there's either a loop around the source or around the target.
  • If there is a loop around say, the source, what is the maximum number of squares it can have?

Problem link

Video Tutorial

You can find the detailed Youtube video tutorial here

国内:B站的视频戳这里

Thought Process

At first, I am puzzled why this problem would be a hard one. It seems simply applying a BFS would get the answer. So here we go.

Brute force, simple BFS

Of course it will hit memory limit because I am allocating a 2-dimensional visited array. Assume boolean is 8 bit -> 1B, 1 Million * 1 Million = 1TB, OMG, immediately using a set instead.

P.S. fun fact, you can use this method to test how much memory leetcode allocate to this problem, you can use binary search and memory is around 300MB

However, this would start hitting Time Limit Exception. Now I begin to notice a few constrains, e.g., the block size is only 200 while the grid is 1M*1M. Simply going from source to target worst case would cause a timeout.

Next thought would be does it help if we sort the block array? While we are doing the BFS, if the block is already larger/smaller than the max/min of the block, we can early stop. However, this won't help if we simply place a block near the target. Also, this would be a nightmare to implement.

Check block loops on source and target

Following the two hints, it would be natural to come up with this idea. Given such huge contrast between the block size (0,200) and the grid size (1M, 1M), all we need to do is to check if there is any loops built by block on source and target b/c if there is a loop, we cannot explore outside of the loop. However, notice if target and source are in the same loop, then we are fine.

There are two ways to early stop this loop checking. One way is to count the BFS steps, the other way is to follow the hints, given 200 blocks, what's the max area it can cover. Given the length 200, Fig 2 in the below graph can result in the largest area. Therefore, we can early terminate the BFS search once we covered more than 19900 blocks. (We can relax this a bit to 20000, doesn't matter)

  • Fig 1 area = 100 * 100 = 10000
  • Fig 2 area = 1 + 2 + 3 + ... + 199 = (1+199)*199/2 = 19900
  • Fig 3 area = 1 * 200 = 200
  • Fig 4 area = 790 (2*Pi*R = 100, thus R = 15.92, Pi * R^2 = 790 )

Solutions

Brute force, simple BFS

 private final int[] xDirection = {1, 0, -1, 0};
private final int[] yDirection = {0, -1, 0, 1};
private final int ONE_MILLION = 1000000; public boolean isEscapePossible(int[][] blocked, int[] source, int[] target) {
if (blocked == null || source == null || target == null) {
return false;
}
Set<String> blockLookup = this.indexBlockedMatrixToSet(blocked); int m = ONE_MILLION;
int n = ONE_MILLION; Set<String> visited = new HashSet<>(); Queue<String> queue = new LinkedList<>(); String sourceString = source[0] + "," + source[1];
queue.offer(sourceString);
visited.add(sourceString); while (!queue.isEmpty()) {
String[] curBlock = queue.poll().split(",");
int curX = Integer.parseInt(curBlock[0]);
int curY = Integer.parseInt(curBlock[1]); if (curX == target[0] && curY == target[1]) {
return true;
} for (int i = 0; i < 4; i++) {
int nextX = curX + xDirection[i];
int nextY = curY + yDirection[i];
if (this.shouldExplore(nextX, nextY, ONE_MILLION, ONE_MILLION, blockLookup, visited)) {
String nextKey = nextX + "," + nextY;
visited.add(nextKey);
queue.offer(nextKey);
}
}
} return false;
} private boolean shouldExplore(
int x,
int y,
int row,
int col,
Set<String> blockLookup,
Set<String> visited) {
if (!(x >= 0 && x < row && y >=0 && y < col)) {
return false;
} String index = x + "," + y;
if (visited.contains(index)) {
return false;
}
if (blockLookup.contains(index)) {
return false;
} return true;
} private Set<String> indexBlockedMatrixToSet(int[][] blocked) {
Set<String> lookup = new HashSet<>(); for (int i = 0; i < blocked.length; i++) {
int x = blocked[i][0];
int y = blocked[i][1];
String index = x + "," + y;
lookup.add(index);
}
return lookup;
}

Time Complexity: O(N), N = 1M * 1M, essentially need to cover the entire huge grid

Space Complexity: O(N), N = 1M*1M, essentially all the nodes need to be put to visited set

Check block loops on source and target

 private final int[] xDirection = {1, 0, -1, 0};
private final int[] yDirection = {0, -1, 0, 1};
private final int ONE_MILLION = 1000000;
private final int MAX_COUNT_THRESHOLD = 20000; public boolean isEscapePossible(int[][] blocked, int[] source, int[] target) {
if (blocked == null || source == null || target == null) {
return false;
} Set<String> blockLookup = this.indexBlockedMatrixToSet(blocked);
boolean isSourceLoop = this.isLoopAroundPoint(source, target, blockLookup);
if (isSourceLoop) {
return false;
} boolean isTargetLoop = this.isLoopAroundPoint(target, source, blockLookup);
if (isTargetLoop) {
return false;
} return true;
} private boolean isLoopAroundPoint(int[] source, int[] target, Set<String> blockLookup) {
int count = 0; Set<String> visited = new HashSet<>();
Queue<String> queue = new LinkedList<>(); String index = source[0] + "," + source[1];
queue.offer(index);
visited.add(index); while (!queue.isEmpty()) {
String[] curBlock = queue.poll().split(",");
int curX = Integer.parseInt(curBlock[0]);
int curY = Integer.parseInt(curBlock[1]); // here think about
if (count >= MAX_COUNT_THRESHOLD) {
return false;
} if (curX == target[0] && curY == target[1]) {
return false;
} for (int i = 0; i < 4; i++) {
int nextX = curX + xDirection[i];
int nextY = curY + yDirection[i]; if (this.shouldExplore(nextX, nextY, ONE_MILLION, ONE_MILLION, blockLookup, visited)) {
String nextKey = nextX + "," + nextY;
count++;
visited.add(nextKey);
queue.offer(nextKey);
}
}
} return true;
} private boolean shouldExplore(
int x,
int y,
int row,
int col,
Set<String> blockLookup,
Set<String> visited) {
if (!(x >= 0 && x < row && y >=0 && y < col)) {
return false;
} String index = x + "," + y;
if (visited.contains(index)) {
return false;
}
if (blockLookup.contains(index)) {
return false;
} return true;
} private Set<String> indexBlockedMatrixToSet(int[][] blocked) {
Set<String> lookup = new HashSet<>(); for (int i = 0; i < blocked.length; i++) {
int x = blocked[i][0];
int y = blocked[i][1];
String index = x + "," + y;
lookup.add(index);
}
return lookup;
}

Time Complexity: O(N), N in terms of block size

Space Complexity: O(N), N in terms of block size

References

Baozi Leetcode solution 1036: Escape a Large Maze的更多相关文章

  1. [Swift]LeetCode1036.逃离大迷宫 | Escape a Large Maze

    In a 1 million by 1 million grid, the coordinates of each grid square are (x, y) with 0 <= x, y & ...

  2. Baozi Leetcode Solution 205: Isomorphic Strings

    Problem Statement Given two strings s and t, determine if they are isomorphic. Two strings are isomo ...

  3. Baozi Leetcode Solution 290: Word Pattern

    Problem Statement Given a pattern and a string str, find if str follows the same pattern. Here follo ...

  4. leetcode solution cracked tutorial

    leetcode solution cracked tutorial problemset https://leetcode.com/problemset/all/ Top Interview Que ...

  5. 【LeetCode】789. Escape The Ghosts 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  6. 【LeetCode】830. Positions of Large Groups 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  7. 73th LeetCode Weekly Contest Escape The Ghosts

    You are playing a simplified Pacman game. You start at the point (0, 0), and your destination is(tar ...

  8. Leetcode solution 291: Word Pattern II

    Problem Statement Given a pattern and a string str, find if str follows the same pattern. Here follo ...

  9. Leetcode solution 227: Basic Calculator II

    Problem Statement Implement a basic calculator to evaluate a simple expression string. The expressio ...

随机推荐

  1. Delphi 10.2 非官方补丁合集

    Delphi 10.2 非官方补丁合集http://blog.qdac.cc/?p=4485 FMXObject和TFORM的释放都变成异步了.虽然能保证是在主线程中释放,但是Windows部分的线程 ...

  2. 浅谈js闭包(closure)

    相信很多从事js开发的朋友都或多或少了解一些有关js闭包(closure)的知识. 本篇文章是从小编个人角度,简单地介绍一下有关js闭包(closure)的相关知识.目的是帮助一些对js开发经验不是很 ...

  3. ngnix 安装

    1安装PCRE库 ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/ 下载最新的 PCRE 源码包,使用下面命令下载编译和安装 PCRE 包: ...

  4. Nio编程模型总结

    终于,这两天的考试熬过去了, 兴致冲冲的来整理笔记来, 这篇博客是我近几天的NIO印象笔记汇总,记录了对Selector及Selector的重要参数的理解,对Channel的理解,常见的Channel ...

  5. react中使用高德地图的原生API

    干货,无话 1.react-create-app,创建新react项目 2.npm install react-amap,引入高德地图的封装 3.编写组件index.js import React f ...

  6. linux:清空文件内容与批量kill 指定程序名的进程

    1.常规的清空文件内容方法 1)使用 cat命令显示 /dev/null 的内容然后重定向输出到某个文件,来清空 $ cat /dev/null > filename 2)清空一个文件可以通过 ...

  7. 18 HTML标签以及属性全

    基本结构标签: <HTML>,表示该文件为HTML文件 <HEAD>,包含文件的标题,使用的脚本,样式定义等 <TITLE>---</TITLE>,包含 ...

  8. 在vuejs 中使用axios不能获取属性data的解决方法

    Laravel5.4 vuejs和axios使用钩子mounted不能获取属性data的解决方法 //出错问题:在then 这个里边的赋值方法this.followed = response.data ...

  9. java模拟键鼠操作

    很久之前百度的,所以忘记了作者,所以仅作为自己的日记纪录在此: package com.robot.test;import java.awt.AWTException;import java.awt. ...

  10. SSM(二)MyBatis多表联查

    这篇文章写了以下几个简单的例子,用来说明MyBatis多标联查基本语法 1.sql片段的用法 2.一对多查询 3.多条sql的一对多查询 4.多对一查询 5.多条sql一对多查询 6.多对多查询 这里 ...