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. vs2008在win7系统中安装不问题

    据说是office软件冲突问题. 解决方案是卸载了office软件,不管是2007还是其它版本,先安装vs2008,再安装其它的.

  2. Redis相关面试题

    Reids:单线程+io多路复用机制 Redis与Memcached的区别: 一.memcached值是简单字符串,redis支持hash.set.list等复杂数据类型 二.redis可持久化数据, ...

  3. 由django请求生命周期延伸出的知识点大总结

    django项目搭建见: https://www.cnblogs.com/dongxixi/p/10981577.html django请求生命周期图: 由浏览器发起请求开始 知识点1: 浏览器与服务 ...

  4. 【Flink】Flink 底层RPC框架分析

    1. 前言 对于Flink中各个组件(JobMaster.TaskManager.Dispatcher等),其底层RPC框架基于Akka实现,本文着重分析Flink中的Rpc框架实现机制及梳理其通信流 ...

  5. Spark学习之路(七)—— 基于ZooKeeper搭建Spark高可用集群

    一.集群规划 这里搭建一个3节点的Spark集群,其中三台主机上均部署Worker服务.同时为了保证高可用,除了在hadoop001上部署主Master服务外,还在hadoop002和hadoop00 ...

  6. 关于Jvm类加载机制,这一篇就够了

    前言 一个月没更新了,这个月发生了太多的事情,导致更新的频率大大降低,不管怎样收拾心情,技术的研究不能落下! jvm作为每个java程序猿必须了解的知识,博主推荐一本书<深入理解Java虚拟机& ...

  7. 【工具】读取proprtties工具类

    获取properties内容: 基本的使用看网络上大多是这样的,使用时注意线程安全以及读写的实时性问题. 1.直接通过流读取(反射): InputStream inStream =  this.get ...

  8. 【转载】一起来学Spring Cloud | Eureka Client注册到Eureka Server的秘密

    LZ看到这篇文章感觉写得比较详细,理解以后,便转载到自己博客中,留作以后回顾学习用,喝水不忘挖井人,内容来自于李刚的博客:http://www.spring4all.com/article/180 一 ...

  9. 数据预处理之独热编码(One-Hot):为什么要使用one-hot编码?

    一.问题由来 最近在做ctr预估的实验时,还没思考过为何数据处理的时候要先进行one-hot编码,于是整理学习如下:  在很多机器学习任务如ctr预估任务中,特征不全是连续值,而有可能是分类值.如下: ...

  10. C++ 洛谷 P2657 [SCOI2009]windy数 题解

    P2657 [SCOI2009]windy数 同步数位DP 这题还是很简单的啦(差点没做出来 个位打表大佬请离开(包括记搜),我这里讲的是DP!!! 首先Cal(b+1)-Cal(a),大家都懂吧(算 ...