[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”( ...
随机推荐
- SQLite学习手册(数据表和视图)
如何列出SQLite数据库中的所有表 SQLite数据库中的信息存在于一个内置表sqlite_master中,在查询器中可以用 select * from sqlite_master 来查看,如果只要 ...
- oracle维护数据的完整性
介绍: 数据的完整性用于确保数据库数据遵从一定的商业的逻辑规则.在oracle中,数据完整性可以使用约束.触发器.应用程序(过程.函数)三种方法来实现,在这三种方法中,因为约束易于维护,并且具有最好的 ...
- C#编写一个大字母游戏,详细代码,不懂问博主。。。。
using System; using System.Drawing; using System.Windows.Forms; using System.Media; namespace dazimu ...
- HASH方法课下补分博客
课堂要求:利用除留余数法为下列关键字集合的存储设计hash函数,并画出分别用开放寻址法和拉链法解决冲突得到的空间存储状态(散列因子取0.75)关键字集合:85,75,57,60,65,(你的8位学号相 ...
- 面试必问---HashMap原理分析
一.HashMap的原理 众所周知,HashMap是用来存储Key-Value键值对的一种集合,这个键值对也叫做Entry,而每个Entry都是存储在数组当中,因此这个数组就是HashMap的主干.H ...
- 开发者的如何优雅的使用OSX
Mac对于IT开发者来说是最好的开发工具,没有之一. 但是对于大部分人来说,第一个接触的PC操作系统都是Windows系统,此文将带大家优雅的快速学习和使用Mac的OSX系统. 1. 从键盘说起 Ma ...
- JAVA_SE基础——3.Java程序的开发流程
上一篇,写的是JAVA的环境变量的配置,今天我抽空写篇Java程序的开发流程,下面的教程是我结合书本和毕向东老师的视频写下的心的~ 在没有真正写Java程序前,首先需要了解Java程序的开发过程. S ...
- python django的ManyToMany简述
Django的多对多关系 在Django的关系中,有一对一,一对多,多对多的关系 我们这里谈的是多对多的关系 ==我们首先来设计一个用于示例的表结构== # -*- coding: utf-8 -*- ...
- URL编码和Base64编码 (转)
我们经常会遇到所谓的URL编码(也叫百分号编码)和Base64编码. 先说一下Bsae64编码.BASE64编码是一种常用的将二进制数据转换为64个可打印字符的编码,常用于在通常处理文本数据 ...
- 作业三:模拟 mysql 进行增删改查
# !/usr/bin/env python3 # _*_coding:utf-8_*_ def help_sql(cmd): if cmd in func_dic.keys(): print('{} ...