[LeetCode] Largest Plus Sign 最大的加型符号
In a 2D grid
from (0, 0) to (N-1, N-1), every cell contains a 1
, except those cells in the given list mines
which are 0
. What is the largest axis-aligned plus sign of 1
s contained in the grid? Return the order of the plus sign. If there is none, return 0.
An "axis-aligned plus sign of 1
s of order k" has some center grid[x][y] = 1
along with 4 arms of length k-1
going up, down, left, and right, and made of 1
s. This is demonstrated in the diagrams below. Note that there could be 0
s or 1
s beyond the arms of the plus sign, only the relevant area of the plus sign is checked for 1s.
Examples of Axis-Aligned Plus Signs of Order k:
Order 1:
000
010
000 Order 2:
00000
00100
01110
00100
00000 Order 3:
0000000
0001000
0001000
0111110
0001000
0001000
0000000
Example 1:
Input: N = 5, mines = [[4, 2]]
Output: 2
Explanation:
11111
11111
11111
11111
11011
In the above grid, the largest plus sign can only be order 2. One of them is marked in bold.
Example 2:
Input: N = 2, mines = []
Output: 1
Explanation:
There is no plus sign of order 2, but there is of order 1.
Example 3:
Input: N = 1, mines = [[0, 0]]
Output: 0
Explanation:
There is no plus sign, so return 0.
Note:
N
will be an integer in the range[1, 500]
.mines
will have length at most5000
.mines[i]
will be length 2 and consist of integers in the range[0, N-1]
.- (Additionally, programs submitted in C, C++, or C# will be judged with a slightly smaller time limit.)
这道题给了我们一个数字N,表示一个NxN的二位数字,初始化均为1,又给了一个mines数组,里面是一些坐标,表示数组中这些位置都为0,然后让我们找最大的加型符号。所谓的加型符号是有数字1组成的一个十字型的加号,题目中也给出了长度分别为1,2,3的加型符号的样子。好,理解了题意以后,我们来想想该如何破题。首先,最简单的就是考虑暴力搜索啦,以每个1为中心,向四个方向分别去找,只要任何一个方向遇到了0就停止,然后更新结果res。令博主感到惊讶的是,此题的OJ居然允许Brute Force的解法通过,还是比较大度的,参见代码如下:
解法一:
class Solution {
public:
int orderOfLargestPlusSign(int N, vector<vector<int>>& mines) {
int res = ;
vector<vector<int>> mat(N, vector<int>(N, ));
for (auto mine : mines) mat[mine[]][mine[]] = ;
for (int i = ; i < N; ++i) {
for (int j = ; j < N; ++j) {
int k = ;
while (canExpand(mat, N, i, j, k)) ++k;
res = max(res, k);
}
}
return res;
}
bool canExpand(vector<vector<int>>& mat, int N, int x, int y, int k) {
if (x - k < || y - k < || x + k >= N || y + k >= N) return false;
return mat[x - k][y] && mat[x][y + k] && mat[x + k][y] && mat[x][y - k];
}
};
如果我们只想出暴力搜索的解法,就不再管这道题了的话,那在面试的时候就比较悬了。毕竟立方级的时间复杂度实在是太高了,我们必须要进行优化。暴力搜索的时间复杂度之所以高的原因是因为对于每一个1都要遍历其上下左右四个方向,有大量的重复计算,我们为了提高效率,可以对于每一个点,都计算好其上下左右连续1的个数。博主最先用的方法是建立四个方向的dp数组,dp[i][j]表示 (i, j) 位置上该特定方向连续1的个数,那么就需要4个二维dp数组,举个栗子,比如:
原数组:
那么我们建立left数组是当前及其左边连续1的个数,如下所示:
right数组是当前及其右边连续1的个数,如下所示:
up数组是当前及其上边连续1的个数,如下所示:
down数组是当前及其下边连续1的个数,如下所示:
我们需要做的是在这四个dp数组中的相同位置的四个值中取最小的一个,然后在所有的这些去除的最小值中选最大一个返回即可。为了节省空间,我们不用四个二维dp数组,而只用一个就可以了,因为对于每一个特定位置,我们只需要保留较小值,所以在更新的时候,只需要跟原来值相比取较小值即可。在计算down数组的时候,我们就可以直接更新结果res了,因为四个值都已经计算过了,我们就不用再重新在外面开for循环了,参见代码如下:
解法二:
class Solution {
public:
int orderOfLargestPlusSign(int N, vector<vector<int>>& mines) {
int res = , cnt = ;
vector<vector<int>> dp(N, vector<int>(N, ));
unordered_set<int> s;
for (auto mine : mines) s.insert(mine[] * N + mine[]);
for (int j = ; j < N; ++j) {
cnt = ;
for (int i = ; i < N; ++i) { // up
cnt = s.count(i * N + j) ? : cnt + ;
dp[i][j] = cnt;
}
cnt = ;
for (int i = N - ; i >= ; --i) { // down
cnt = s.count(i * N + j) ? : cnt + ;
dp[i][j] = min(dp[i][j], cnt);
}
}
for (int i = ; i < N; ++i) {
cnt = ;
for (int j = ; j < N; ++j) { // left
cnt = s.count(i * N + j) ? : cnt + ;
dp[i][j] = min(dp[i][j], cnt);
}
cnt = ;
for (int j = N - ; j >= ; --j) { // right
cnt = s.count(i * N + j) ? : cnt + ;
dp[i][j] = min(dp[i][j], cnt);
res = max(res, dp[i][j]);
}
}
return res;
}
};
我们可以进一步的压缩代码,使其更加简洁,我们发现其实只要分别用四个变量l,r,u,d来表示四个方向连续1的个数,既可以将for循环糅合在一起。注意里面内嵌的for循环其实是两个for循环,由j和k分别控制,那么只要弄清i,j,k坐标的位置,就可以同时更新四个方向的dp值了,最后dp数组更新好了之后,我们再秀一波,只用一个for循环来遍历二维数组,其实就是把二维坐标压缩成了一个数字,再解压缩,参见代码如下:
解法三:
class Solution {
public:
int orderOfLargestPlusSign(int N, vector<vector<int>>& mines) {
int res = ;
vector<vector<int>> dp(N, vector<int>(N, N));
for (auto mine : mines) dp[mine[]][mine[]] = ;
for (int i = ; i < N; ++i) {
int l = , r = , u = , d = ;
for (int j = , k = N - ; j < N; ++j, --k) {
dp[i][j] = min(dp[i][j], l = (dp[i][j] ? l + : ));
dp[j][i] = min(dp[j][i], u = (dp[j][i] ? u + : ));
dp[i][k] = min(dp[i][k], r = (dp[i][k] ? r + : ));
dp[k][i] = min(dp[k][i], d = (dp[k][i] ? d + : ));
}
}
for (int k = ; k < N * N; ++k) res = max(res, dp[k / N][k % N]);
return res;
}
};
类似题目:
Cheapest Flights Within K Stops
Minimum Swaps To Make Sequences Increasing
Soup Servings
参考资料:
https://leetcode.com/problems/largest-plus-sign/solution/
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Largest Plus Sign 最大的加型符号的更多相关文章
- 【LeetCode】764. Largest Plus Sign 解题报告(Python)
[LeetCode]764. Largest Plus Sign 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn ...
- 【leetcode】Largest Plus Sign
题目如下: In a 2D grid from (0, 0) to (N-1, N-1), every cell contains a 1, except those cells in the giv ...
- [Swift]LeetCode764. 最大加号标志 | Largest Plus Sign
In a 2D grid from (0, 0) to (N-1, N-1), every cell contains a 1, except those cells in the given lis ...
- leetcode Largest Rectangle in Histogram 单调栈
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4052343.html 题目链接 leetcode Largest Rectangle in ...
- 764. Largest Plus Sign最大的dfs十字架
[抄题]: 求挖掉一些区域后,能允许出现的最大十字架 In a 2D grid from (0, 0) to (N-1, N-1), every cell contains a 1, except t ...
- [LeetCode] Largest Rectangle in Histogram O(n) 解法详析, Maximal Rectangle
Largest Rectangle in Histogram Given n non-negative integers representing the histogram's bar height ...
- 解决VS2012【加载......符号缓慢】的问题
http://blog.csdn.net/shi0090/article/details/19411777 最近在用VS2012调试时,经常出现"加载......符号缓慢的问题", ...
- 解决Visual Studio 加载符号卡死情况
VS 加载符号 过慢或卡死的情况都可以用这种方法 打开VS的[工具]-[选项]-[调试]-[符号], 如下图所示: 1. 先取消勾选 ”Microsoft符号服务器” 2. 再点击 “清空符号缓存” ...
- 在c++运行后出现PDB或者什么巴拉巴拉已经加载符号了的话
“stl常用排序算法.exe”(Win32): 已加载“E:\vs2015\project\stl常用排序算法\Debug\stl常用排序算法.exe”.已加载符号. “stl常用排序算法.exe”( ...
随机推荐
- DB2开发系列之三——SQL函数
1.内置函数分类(SYSIBM模式内) 1)标量函数:返回一个标量值的函数: 2)聚合函数:也叫列函数,也返回一个标量值,这个值是一组输入值的计算结果:3)表函数:向引用它的 SQL 语句返回一个表: ...
- Nginx技巧——Nginx/Apache下禁止指定目录运行PHP脚本(转自运维之美)
网站程序的上传目录通常是不需要PHP执行解释权限,通过限制目录的PHP执行权限可以提网站的安全性,减少被攻击的机率. 下面和大家一起分享下如何在Apache和Nginx禁止上传目录里PHP的执行权限. ...
- Java基础学习笔记二十 IO流
转换流 在学习字符流(FileReader.FileWriter)的时候,其中说如果需要指定编码和缓冲区大小时,可以在字节流的基础上,构造一个InputStreamReader或者OutputStre ...
- C语言博客作业—数据类型
一.PTA实验作业 题目1: 1. 本题PTA提交列表 2. 设计思路 (2)if(输入的n为奇数){ for(行数小于n/2+1时){ for(空格数等于n-2*k+1) printf(" ...
- B-dya6
1.昨天的困难,今天解决的进度,以及明天要做的事情 昨天的困难:在导入导出方面遇到了困难,导出的文件不能直接导入. 今天解决的进度:完成了登录页面的背景设计,并再次测试了整个系统的功能. 明天要做的事 ...
- mysql基础篇 - 其他基本操作
基础篇 - 其他基本操作 其他基本操作 一.实验简介 本节实验中我们将学习并实践数据库的其他基本操作:索引.视图,导入和导出,备份和恢复等. 这些概念对于数据库管理员而言都非常重要,请 ...
- Flask 扩展 用户会话
pip install flask-login 接下来创建扩展对象实例: from flask import Flask from flask_login import LoginManager ap ...
- js 选择图片生成base64数据
<!doctype html> <html> <head> <meta charset="utf-8"> <meta http ...
- WPF自学入门(十)WPF MVVM简单介绍
前面文章中,我们已经知道,WPF技术的主要特点是数据驱动UI,所以在使用WPF技术开发的过程中是以数据为核心的,WPF提供了数据绑定机制,当数据发生变化时,WPF会自动发出通知去更新UI. 我们不管 ...
- es6+react.js组件入门初探
React是一个用于构建用户见面的javascript库. React主要用于构建UI,许多人认为React是MVC中的V(视图) React起源于Facebook的内部项目,用来架设Instagra ...