[LeetCode] 694. Number of Distinct Islands 不同岛屿的个数
Given a non-empty 2D array grid
of 0's and 1's, an island is a group of 1
's (representing land) connected 4-directionally (horizontal or vertical.) You may assume all four edges of the grid are surrounded by water.
Count the number of distinct islands. An island is considered to be the same as another if and only if one island can be translated (and not rotated or reflected) to equal the other.
Example 1:
11000
11000
00011
00011
Given the above grid map, return 1
.
Example 2:
11011
10000
00001
11011
Given the above grid map, return 3
.
Notice that:
11
1
and
1
11
are considered different island shapes, because we do not consider reflection / rotation.
Note: The length of each dimension in the given grid
does not exceed 50.
这道题让我们求不同岛屿的个数,是之前那道 Number of Islands 的拓展,难点是如何去判断两个岛屿是否是不同的岛屿,首先1的个数肯定是要相同,但是1的个数相同不能保证一定是相同的岛屿,比如例子2中的那两个岛屿的就不相同,就是说两个相同的岛屿通过平移可以完全重合,但是不能旋转。如何来判断呢,可以发现可以通过相对位置坐标来判断,比如使用岛屿的最左上角的1当作基点,那么基点左边的点就是 (0,-1),右边的点就是 (0,1), 上边的点就是 (-1,0),下面的点就是 (1,0)。则例子1中的两个岛屿都可以表示为 [(0,0), (0,1), (1,0), (1,1)],点的顺序是基点-右边点-下边点-右下点。通过这样就可以判断两个岛屿是否相同了,下面这种解法没有用数组来存,而是 encode 成了字符串,比如这四个点的数组就存为 "0_0_0_1_1_0_1_1_",然后把字符串存入集合 unordered_set 中,利用其自动去重复的特性,就可以得到不同的岛屿的数量啦,参见代码如下:
解法一:
class Solution {
public:
vector<vector<int>> dirs{{,-},{-,},{,},{,}};
int numDistinctIslands(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[].size();
unordered_set<string> res;
vector<vector<bool>> visited(m, vector<bool>(n, false));
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (grid[i][j] == && !visited[i][j]) {
set<string> s;
helper(grid, i, j, i, j, visited, s);
string t = "";
for (auto str : s) t += str + "_";
res.insert(t);
}
}
}
return res.size();
}
void helper(vector<vector<int>>& grid, int x0, int y0, int i, int j, vector<vector<bool>>& visited, set<string>& s) {
int m = grid.size(), n = grid[].size();
visited[i][j] = true;
for (auto dir : dirs) {
int x = i + dir[], y = j + dir[];
if (x < || x >= m || y < || y >= n || grid[x][y] == || visited[x][y]) continue;
string str = to_string(x - x0) + "_" + to_string(y - y0);
s.insert(str);
helper(grid, x0, y0, x, y, visited, s);
}
}
};
当然我们也可以不 encode 字符串,直接将相对坐标存入数组中,然后把整个数组放到集合 set 中,还是会去掉相同的数组,而且这种解法直接在 grid 数组上标记访问过的位置,写起来更加简洁了,参见代码如下:
解法二:
class Solution {
public:
vector<vector<int>> dirs{{,-},{-,},{,},{,}};
int numDistinctIslands(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[].size();
set<vector<pair<int, int>>> res;
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (grid[i][j] != ) continue;
vector<pair<int, int>> v;
helper(grid, i, j, i, j, v);
res.insert(v);
}
}
return res.size();
}
void helper(vector<vector<int>>& grid, int x0, int y0, int i, int j, vector<pair<int, int>>& v) {
int m = grid.size(), n = grid[].size();
if (i < || i >= m || j < || j >= n || grid[i][j] <= ) return;
grid[i][j] *= -;
v.push_back({i - x0, j - y0});
for (auto dir : dirs) {
helper(grid, x0, y0, i + dir[], j + dir[], v);
}
}
};
既然递归 DFS 可以,那么迭代的 BFS 就坐不住了,其实思路没什么区别,这种类似迷宫遍历的题都是一个套路,整体框架都很像,细枝末节需要改改就行了,参见代码如下:
解法三:
class Solution {
public:
vector<vector<int>> dirs{{,-},{-,},{,},{,}};
int numDistinctIslands(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[].size();
set<vector<pair<int, int>>> res;
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (grid[i][j] != ) continue;
vector<pair<int, int>> v;
queue<pair<int, int>> q{{{i, j}}};
grid[i][j] *= -;
while (!q.empty()) {
auto t = q.front(); q.pop();
for (auto dir : dirs) {
int x = t.first + dir[], y = t.second + dir[];
if (x < || x >= m || y < || y >= n || grid[x][y] <= ) continue;
q.push({x, y});
grid[x][y] *= -;
v.push_back({x - i, y - j});
}
}
res.insert(v);
}
}
return res.size();
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/694
类似题目:
参考资料:
https://leetcode.com/problems/number-of-distinct-islands/
https://leetcode.com/problems/number-of-distinct-islands/discuss/150037/DFS-with-Explanations
https://leetcode.com/problems/number-of-distinct-islands/discuss/108474/JavaC%2B%2B-Clean-Code
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] 694. Number of Distinct Islands 不同岛屿的个数的更多相关文章
- [LeetCode] Number of Distinct Islands 不同岛屿的个数
Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) conn ...
- [leetcode]694. Number of Distinct Islands你究竟有几个异小岛?
Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) conn ...
- [LeetCode] 694. Number of Distinct Islands
Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) conn ...
- [LeetCode] 711. Number of Distinct Islands II_hard tag: DFS
Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) conn ...
- leetcode 200. Number of Islands 、694 Number of Distinct Islands 、695. Max Area of Island 、130. Surrounded Regions
两种方式处理已经访问过的节点:一种是用visited存储已经访问过的1:另一种是通过改变原始数值的值,比如将1改成-1,这样小于等于0的都会停止. Number of Islands 用了第一种方式, ...
- [LeetCode] 711. Number of Distinct Islands II 不同岛屿的个数之二
Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) conn ...
- 694. Number of Distinct Islands 形状不同的岛屿数量
[抄题]: Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land ...
- 【LeetCode】694. Number of Distinct Islands 解题报告 (C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 DFS 日期 题目地址:https://leetcod ...
- [LeetCode] Number of Distinct Islands II 不同岛屿的个数之二
Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) conn ...
随机推荐
- SQL Server 判断各种对象是否存在和sysobjects的关系
一.判断表是否存在 object_id():获取表的ID,其中N表示Unicode类型.可以支持不同语种的对象名 ) drop table [dbo].[表名] 二.判断要创建的存储过程名是否存在 ) ...
- Mysql 二进制日志备份还原
Mysql 二进制日志备份还原 一.开启二进制日志 1.进入配置文件[mysqld]下添加配置 方案一 vim /etc/my.cnf log-bin = /usr/local/mysql/logs/ ...
- [CrackMe]160个CrackMe之002
吾爱破解专题汇总:[反汇编练习]160个CrackME索引目录1~160建议收藏备用 一.逆向分析之暴力破解 暴力破解,对于这种具有提示框的,很好定位. 定位好之后,爆破其跳转语句,就能达到破解目的. ...
- 嵌入式Linux+NetCore 笔记一
记录嵌入式Linux+NetCore培训中遇到的一些问题以及解决方法 十一放假期间发现园里大神大石头(NewLife团队)开了一个嵌入式Linux+NetCore培训,就报名参加了.更幸运的是,我刚好 ...
- .NET 跨域问题解决
后端处理:var callback=context.Request.QueryString["callback"].ToString(); context.Response.Wri ...
- maplotlib画柱状图并添加标签
import json from collections import Counter import matplotlib.pyplot as plt import matplotlib as mpl ...
- jsonp格式前端发送和后台接受写法
jsonp是ajax提交的一种格式不会受跨域限制 一.前端发送 <button>11111</button> <script src="https://cdn. ...
- python3的hashlib库sha256、pbkdf2_hmac、blake2b基本用法
hashlib.sha256: import hashlib x = hashlib.sha256()x.update(b"asd")print("x_1 = " ...
- Java面向对象——相关基本定义
Java面向对象——相关基本定义 摘要:本文简单介绍了面向对象的编程方式,以及与之有关的一些基本定义. 面向对象 什么是面向对象 面向对象编程是一种对现实世界建立计算机模型的一种编程方法.简称OOP( ...
- Python3返回函数
函数作为返回值 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回. 我们来实现一个可变参数的求和.通常情况下,求和的函数是这样定义的: def calc_sum(*args): ax = ...