周末加餐 使陆地分离的最少天数
给你一个由若干 0 和 1 组成的二维网格 grid ,其中 0 表示水,而 1 表示陆地。岛屿由水平方向或竖直方向上相邻的 1(陆地)连接形成。
如果恰好只有一座岛屿 ,则认为陆地是连通的 ;否则,陆地就是分离的 。一天内,可以将任何单个陆地单元(1)更改为水单元(0)。返回使陆地分离的最少天数。
示例 1: 输入:grid = [[0,1,1,0],[0,1,1,0],[0,0,0,0]] 输出:2 解释:至少需要 2天才能得到分离的陆地。 将陆地 grid[1][1] 和 grid[0][2] 更改为水,得到两个分离的岛屿。
示例 2: 输入:grid = [[1,1]]
输出:2 解释:如果网格中都是水,也认为是分离的 ([[1,1]] -> [[0,0]]),0 岛屿。
示例 3: 输入:grid = [[1,0,1,0]] 输出:0
示例 4: 输入:grid = [
[1,1,0,1,1],
[1,1,1,1,1],
[1,1,0,1,1],
[1,1,0,1,1]] 输出:1
示例 5: 输入:grid = [
[1,1,0,1,1],
[1,1,1,1,1],
[1,1,0,1,1],
[1,1,1,1,1]] 输出:2
花了一段时间想到答案不是0就是1,不是1就是2。判断是否是0挺简单的,找到一个1计算连通的1的个数,并与grid中1的总数进行比较。判断是否是1就比较麻烦了,直接的想法是挨个删一删试试,用和上面相同的办法进行判断:
class Solution {int countLand(int[][] grid, int row, int col) {grid[row][col] = 0;int ans = 1;if(row < grid.length - 1 && grid[row + 1][col] == 1) {ans += countLand(grid, row + 1, col);}if(col < grid[0].length - 1 && grid[row][col + 1] == 1) {ans += countLand(grid, row, col + 1);}if(row > 0 && grid[row - 1][col] == 1) {ans += countLand(grid, row - 1, col);}if(col > 0 && grid[row][col - 1] == 1) {ans += countLand(grid, row, col - 1);}return ans; }boolean isSplit(int[][] grid, int num) {if(num == 0)return true;if(num == 1)return false;//找到第一个1 搜索 比较连通的陆地大小是不是陆地总大小for(int i = 0; i < grid.length; ++i)for(int j = 0; j < grid[0].length; ++j) {if(grid[i][j] == 1) {int[][] copy = new int[grid.length][];for (int ii = 0; ii < grid.length; ii++) {copy[ii] = new int[grid[ii].length];System.arraycopy(grid[ii], 0, copy[ii], 0, grid[ii].length);}return countLand(copy, i, j) != num;}}return false;} public int minDays(int[][] grid) {//还真被吓到了//答案最大不超过2int num = 0;for(int i = 0; i < grid.length; ++i) for(int j = 0; j < grid[0].length; ++j) {if(grid[i][j] == 1)++num;}if(isSplit(grid, num)) {return 0;}for(int i = 0; i < grid.length; ++i) for(int j = 0; j < grid[0].length; ++j) {if(grid[i][j] == 1) {grid[i][j] = 0;if(isSplit(grid, num - 1)) {return 1;}grid[i][j] = 1;}}return 2;}
}
27ms 居然没有超时。
看了看别人的参考,有说用Tarjan法的,搜了一下,这篇感觉写的挺好的:Tarjan法求割点。基本上是dfs并对搜索到的树进行判断。判断自己和子树靠返回边能到的序号和父节点的序号,如果返回边等到达的序号不小于父节点的序号,那去了父节点肯定完蛋。实现了一下:
class Solution {int countLand(int[][] grid, int row, int col) {grid[row][col] = 0;int ans = 1;if(row < grid.length - 1 && grid[row + 1][col] == 1) {ans += countLand(grid, row + 1, col);}if(col < grid[0].length - 1 && grid[row][col + 1] == 1) {ans += countLand(grid, row, col + 1);}if(row > 0 && grid[row - 1][col] == 1) {ans += countLand(grid, row - 1, col);}if(col > 0 && grid[row][col - 1] == 1) {ans += countLand(grid, row, col - 1);}return ans; }boolean isSplit(int[][] grid, int num) {if(num == 0)return true;if(num == 1)return false;//找到第一个1 搜索 比较连通的陆地大小是不是陆地总大小for(int i = 0; i < grid.length; ++i)for(int j = 0; j < grid[0].length; ++j) {int[][] copy = new int[grid.length][];for (int ii = 0; ii < grid.length; ii++) {copy[ii] = new int[grid[ii].length];System.arraycopy(grid[ii], 0, copy[ii], 0, grid[ii].length);}if(grid[i][j] == 1 && countLand(copy, i, j) != num) {return true;}}return false;} int curDfn;int[][] dfn;int[][] low;int firstChilds;boolean cut;void processPoint(int[][] grid, int curR, int curC, int nextR, int nextC, int from) {if(cut == true)return;if(dfn[nextR][nextC] == 0) {++curDfn;dfn[nextR][nextC] = curDfn;low[nextR][nextC] = curDfn;dfs(grid, nextR, nextC, from);low[curR][curC] = Math.min(low[curR][curC], low[nextR][nextC]);if(dfn[curR][curC] != 1 && low[nextR][nextC] >= dfn[curR][curC])cut = true;if(dfn[curR][curC] == 1)++firstChilds;} else {low[curR][curC] = Math.min(low[curR][curC], low[nextR][nextC]);}}void dfs(int[][] grid, int row, int col, int from) {if(cut == true)return;if(row < grid.length - 1 && grid[row + 1][col] == 1 && from != 0) {processPoint(grid, row, col, row + 1, col, 2);}if(col < grid[0].length - 1 && grid[row][col + 1] == 1 && from != 1) {processPoint(grid, row, col, row, col + 1, 3);}if(row > 0 && grid[row - 1][col] == 1 && from != 2) {processPoint(grid, row, col, row - 1, col, 0);}if(col > 0 && grid[row][col - 1] == 1 && from != 3) {processPoint(grid, row, col, row, col - 1, 1);}}boolean hasCut(int[][] grid) {cut = false;dfn = new int[grid.length][grid[0].length];//维护访问次序low = new int[grid.length][grid[0].length];//维护回溯能达到的最小数值for(int i = 0; i < grid.length; ++i) for(int j = 0; j < grid[0].length; ++j){if(grid[i][j] == 1) {dfn[i][j] = 1;low[i][j] = 1;curDfn = 1;dfs(grid, i, j, -1);return cut || firstChilds > 1;}}return cut;}public int minDays(int[][] grid) {int num = 0;for(int i = 0; i < grid.length; ++i) for(int j = 0; j < grid[0].length; ++j) {if(grid[i][j] == 1)++num;}if(isSplit(grid, num)) {return 0;}if(hasCut(grid)) {return 1;}return 2;}
}
因为是在方法1基础上改的,所以对于初始情况的判别用的和上次一样的方法。居然是74ms…怎么正经做反而慢了啊
周末加餐 使陆地分离的最少天数相关推荐
- LeetCode 1568. 使陆地分离的最少天数(DFS)
文章目录 1. 题目 2. 解题 1. 题目 给你一个由若干 0 和 1 组成的二维网格 grid ,其中 0 表示水,而 1 表示陆地. 岛屿由水平方向或竖直方向上相邻的 1 (陆地)连接形成. 如 ...
- leetcode1568. 使陆地分离的最少天数(Python3、c++)
文章目录 leetcode1568. 使陆地分离的最少天数 方法:并查集 思路: 并查集: 求割点: 代码: Python3: cpp: 结果: leetcode1568. 使陆地分离的最少天数 给你 ...
- 五、c++学习(加餐1:汇编基础学习)
经过前面几节课的学习,我们在一些地方都会使用汇编来分析,我们学习汇编,只是学习一些基础,主要是在我们需要深入分析语法的时候,使用汇编分析,这样会让我们更熟悉c++编译器和语法. 从这节课开始,会持续加 ...
- 【加餐】如何在SteamVR 2 中替换手部模型
根据学员朋友的反馈,新增3节加餐课时,关于如何在新版SteamVR中基于Skeleton Input实现手部模型的替换. 在VR应用程序中,要呈现自制的手部模型,传统的方式是直接将模型导入,放置在手柄 ...
- Lesson13【加餐】 损失函数的随机创建现象详解
[Lesson 13 加餐]损失函数的随机创建现象详解 接下来,我们通过手动创建一个实例,来观察在小批梯度下降过程中,损失函数是如何根据数据数据变化而变化的,这里既是作为本节内容的一个补充,同时也 ...
- 旋转矩阵求旋转角度_(加餐)欧拉角及矩阵旋转
(1 本文约2000字,大约需要阅读20分钟)(2 本文适合有一定雷达及信号与系统知识基础的读者) 乡亲们大家好,今天的这期内容就像有钱人的生活,比较枯燥,不过能完整读下来也确能有所收获,本文是分析微 ...
- LeetCode 1674. 使数组互补的最少操作次数(差分思想)
文章目录 1. 题目 2. 解题 1. 题目 给你一个长度为 偶数 n 的整数数组 nums 和一个整数 limit . 每一次操作,你可以将 nums 中的任何整数替换为 1 到 limit 之间的 ...
- LeetCode 1653. 使字符串平衡的最少删除次数(DP)
文章目录 1. 题目 2. 解题 1. 题目 给你一个字符串 s ,它仅包含字符 'a' 和 'b' . 你可以删除 s 中任意数目的字符,使得 s 平衡 . 我们称 s 平衡的 当不存在下标 ...
- 使括号有效的最少添加
使括号有效的最少添加 给定一个由(和)括号组成的字符串S,我们需要添加最少的括号(或是),可以在任何位置,以使得到的括号字符串有效. 从形式上讲,只有满足下面几点之一,括号字符串才是有效的: 它是一个 ...
最新文章
- 二维物体形状识别方法比较
- python使用fpdf将生成的长字符串手动换行写入pdf
- Javascript 绑定事件和 this理解
- java面向对象的特征三:多态性 —(15)
- java 线程什么时候出栈_在Java中给出的时间
- html:(17):img标签和表单标签
- C++STL与泛型编程(3)容器之分类与测试
- 【实践】BiLSTM上的CRF,用命名实体识别任务来解释CRF(2)损失函数
- 线报采集监控|人工智能+线报采集算法+大数据过滤无效线报
- 生物信息预测毒力因子
- 五险一金,这篇就够了
- 解决win10可以登录微信/QQ,浏览器无法访问网页的问题
- [转] 从1个月到2岁半的育儿方案,有了它宝宝都不用去上早教啦
- Java基础系列-《流程控制--循环结构》
- 数分下(第1讲):一阶微分方程的三类模型求解
- LSL学习笔记(4)
- 使用 AIX TCP/IP 过滤功能设置防火墙
- 视觉SLAM:一直在入门,从未到精通
- 组图:1936年柏林奥运会
- 柠檬水找零---贪心算法(c++)实现