Java实现 LeetCode 749 隔离病毒(DFS嵌套)
749. 隔离病毒
病毒扩散得很快,现在你的任务是尽可能地通过安装防火墙来隔离病毒。
假设世界由二维矩阵组成,0 表示该区域未感染病毒,而 1 表示该区域已感染病毒。可以在任意 2 个四方向相邻单元之间的共享边界上安装一个防火墙(并且只有一个防火墙)。
每天晚上,病毒会从被感染区域向相邻未感染区域扩散,除非被防火墙隔离。现由于资源有限,每天你只能安装一系列防火墙来隔离其中一个被病毒感染的区域(一个区域或连续的一片区域),且该感染区域对未感染区域的威胁最大且保证唯一。
你需要努力使得最后有部分区域不被病毒感染,如果可以成功,那么返回需要使用的防火墙个数; 如果无法实现,则返回在世界被病毒全部感染时已安装的防火墙个数。
示例 1:
输入: grid =
[[0,1,0,0,0,0,0,1],
[0,1,0,0,0,0,0,1],
[0,0,0,0,0,0,0,1],
[0,0,0,0,0,0,0,0]]
输出: 10
说明:
一共有两块被病毒感染的区域: 从左往右第一块需要 5 个防火墙,同时若该区域不隔离,晚上将感染 5 个未感染区域(即被威胁的未感染区域个数为 5);
第二块需要 4 个防火墙,同理被威胁的未感染区域个数是 4。因此,第一天先隔离左边的感染区域,经过一晚后,病毒传播后世界如下:
[[0,1,0,0,0,0,1,1],
[0,1,0,0,0,0,1,1],
[0,0,0,0,0,0,1,1],
[0,0,0,0,0,0,0,1]]
第二题,只剩下一块未隔离的被感染的连续区域,此时需要安装 5 个防火墙,且安装完毕后病毒隔离任务完成。
示例 2:
输入: grid =
[[1,1,1],
[1,0,1],
[1,1,1]]
输出: 4
说明:
此时只需要安装 4 面防火墙,就有一小区域可以幸存,不被病毒感染。
注意不需要在世界边界建立防火墙。
示例 3:
输入: grid =
[[1,1,1,0,0,0,0,0,0],
[1,0,1,0,1,1,1,1,1],
[1,1,1,0,0,0,0,0,0]]
输出: 13
说明:
在隔离右边感染区域后,隔离左边病毒区域只需要 2 个防火墙了。
说明:
grid 的行数和列数范围是 [1, 50]。
grid[i][j] 只包含 0 或 1 。
题目保证每次选取感染区域进行隔离时,一定存在唯一一个对未感染区域的威胁最大的区域。
class Solution {
int n, m;
boolean[][] visited;
Set<Integer> set = new TreeSet<>();
public int containVirus(int[][] grid) {
int res = 0;
n = grid.length;
m = grid[0].length;
while (true){
visited = new boolean[n][m];
PriorityQueue<int[]> q = new PriorityQueue<>(((o1, o2) -> o2[0]-o1[0]));
for (int i = 0; i < n; i++){
for (int j = 0; j < m; j++){
if (!visited[i][j] && grid[i][j] == 1){
set.clear();
int barriers = dfs(grid, i, j);
int infected = set.size();
q.offer(new int[]{infected, barriers, index(i, j)});
}
}
}
if (q.size() == 0){
break;
}
int[] t = q.poll();
res += t[1];
dfs1(grid, t[2] / m, t[2] % m);
for (int i = 0; i < n; i++){
Arrays.fill(visited[i], false);
}
for (int i = 0; i < n; i++){
for (int j = 0; j < m; j++){
if (!visited[i][j] && grid[i][j] == 1){
dfs2(grid, i, j);
}
}
}
}
return res;
}
private void dfs2(int[][] grid, int i, int j) {
if (grid[i][j] == 2){
return;
}
visited[i][j] = true;
if (i - 1 >= 0 && !visited[i - 1][j]){
if (grid[i - 1][j] == 0){
grid[i - 1][j] = 1;
visited[i - 1][j] = true;
}else{
dfs2(grid, i - 1, j);
}
}
if (i + 1 < n && !visited[i + 1][j]){
if (grid[i + 1][j] == 0){
grid[i + 1][j] = 1;
visited[i + 1][j] = true;
}else{
dfs2(grid, i + 1, j);
}
}
if (j - 1 >= 0 && !visited[i][j - 1]){
if (grid[i][j - 1] == 0){
grid[i][j - 1] = 1;
visited[i][j - 1] = true;
}else{
dfs2(grid, i, j - 1);
}
}
if (j + 1 < m && !visited[i][j + 1]){
if (grid[i][j + 1] == 0){
grid[i][j + 1] = 1;
visited[i][j + 1] = true;
}else{
dfs2(grid, i, j + 1);
}
}
}
private void dfs1(int[][] grid, int i, int j) {
grid[i][j] = 2;
if (i - 1 >= 0){
if (grid[i - 1][j] == 1){
dfs1(grid, i - 1, j);
}
}
if (i + 1 < n){
if (grid[i + 1][j] == 1){
dfs1(grid, i + 1, j);
}
}
if (j - 1 >= 0){
if (grid[i][j - 1] == 1){
dfs1(grid, i, j - 1);
}
}
if (j + 1 < m){
if (grid[i][j + 1] == 1){
dfs1(grid, i, j + 1);
}
}
}
private int dfs(int[][] grid, int i, int j) {
if (grid[i][j] == 2){
return 0;
}
visited[i][j] = true;
int cur = 0;
if (i - 1 >= 0 && !visited[i - 1][j]){
if (grid[i - 1][j] == 0){
cur++;
set.add(index(i - 1, j));
}else{
cur += dfs(grid, i - 1, j);
}
}
if (i + 1 < n && !visited[i + 1][j]){
if (grid[i + 1][j] == 0){
cur++;
set.add(index(i + 1 ,j));
}else{
cur += dfs(grid, i + 1, j);
}
}
if (j - 1 >= 0 && !visited[i][j - 1]){
if (grid[i][j - 1] == 0){
cur++;
set.add(index(i, j - 1));
}else{
cur += dfs(grid, i, j - 1);
}
}
if (j + 1 < m && !visited[i][j + 1]){
if (grid[i][j + 1] == 0){
cur++;
set.add(index(i, j + 1));
}else{
cur += dfs(grid, i, j + 1);
}
}
return cur;
}
private int index(int i, int j){
return m * i + j;
}
}
Java实现 LeetCode 749 隔离病毒(DFS嵌套)的更多相关文章
- Java实现 LeetCode 1111 有效括号的嵌套深度(阅读理解题,位运算)
1111. 有效括号的嵌套深度 有效括号字符串 定义:对于每个左括号,都能找到与之对应的右括号,反之亦然.详情参见题末「有效括号字符串」部分. 嵌套深度 depth 定义:即有效括号字符串嵌套的层数, ...
- Java实现 LeetCode 529 扫雷游戏(DFS)
529. 扫雷游戏 让我们一起来玩扫雷游戏! 给定一个代表游戏板的二维字符矩阵. 'M' 代表一个未挖出的地雷,'E' 代表一个未挖出的空方块,'B' 代表没有相邻(上,下,左,右,和所有4个对角线) ...
- Java for LeetCode 216 Combination Sum III
Find all possible combinations of k numbers that add up to a number n, given that only numbers from ...
- Java for LeetCode 212 Word Search II
Given a 2D board and a list of words from the dictionary, find all words in the board. Each word mus ...
- Java for LeetCode 047 Permutations II
Given a collection of numbers that might contain duplicates, return all possible unique permutations ...
- [Swift]LeetCode749. 隔离病毒 | Contain Virus
A virus is spreading rapidly, and your task is to quarantine the infected area by installing walls. ...
- Java for LeetCode 126 Word Ladder II 【HARD】
Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from ...
- Java for LeetCode 098 Validate Binary Search Tree
Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as ...
- Java for LeetCode 095 Unique Binary Search Trees II
Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. For e ...
随机推荐
- 【MySQL基础总结】运算符的使用
运算符的使用 算数运算符 比较运算符 结果只能为TRUE(1)或FALSE(0) 逻辑运算符 运算符的优先级 可以通过括号改变优先级 示例 算数运算符 比较运算符 逻辑运算符
- ASP.NET Core中结合枚举和资源文件显示列表
模型类的某些属性以枚举形式出现,我们希望在打开编辑表单时在选择列表中显示枚举值.有时我们想要枚举元素名称,但有时我们想要使用自定义名称甚至翻译. 这个例子演示了如何获取枚举元素名称以选择ASP.NET ...
- [poj2778 DNA Sequence]AC自动机,矩阵快速幂
题意:给一些字符串的集合S和整数n,求满足 长度为n 只含charset = {'A'.'T‘.'G'.'C'}包含的字符 不包含S中任一字符串 的字符串的种类数. 思路:首先对S建立ac自动机,考虑 ...
- 06JAVA面向对象之封装
一.面向对象 1.面向过程和面向对象 面向过程 分析问题的步骤,然后逐步实现. 面向对象 (1)面向对象基于面向过程 (2)面向对象是找出解决问题的人,然后分配职责. (3)对象中包含解决问题的步骤 ...
- javaWeb删除一条及多条数据
一.编写dao //删除根据ID@Delete("delete from product where id=#{id}")public void delete(Integer id ...
- JS的IIFE
1. 定义 IIFE: Immediately Invoked Function Expression,意为立即调用的函数表达式,也就是说,声明函数的同时立即调用这个函数. 首先我们要了解一般情况下什 ...
- mysql5.6 thread pool
从percona 的压测来看,确实很牛笔啊.提升很大. http://www.mysqlperformanceblog.com/2014/01/29/percona-server-thread-poo ...
- 【C#】CsvHelper 使用手册
目录 简介 模块 读取 读取所有记录 逐条读取 读取单个字段 写入 写入所有记录 逐条写入 逐字段写入 特性 Index Name NameIndex Ignore Optional Default ...
- 【雕爷学编程】MicroPython动手做(04)——零基础学MaixPy之尝试运行
1.hello micropython #MicroPython动手做(04)——零基础学MaixPy之基本示例 #程序之一:hello micropython #MicroPython动手做(04) ...
- 微信小程序入门知识点总结
微信小程序入门知识点总结 前情介绍 微信小程序就不多介绍了,我们想要开发微信小程序首先得到微信公众平台 下方的小程序处注册相关账号并登录,接着填写小程序相关资料.在设置处可找到AppID用以开发微 ...