Number of Distinct Islands - LintCode

204 篇文章 0 订阅

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.

Notice that:

11
1

and

 1
11

are considered different island shapes, because we do not consider reflection / rotation.

注意事项
The length of each dimension in the given grid does not exceed 50.

样例

Given grid = 
[
[1,1,0,0,0],
[1,1,0,0,0],
[0,0,0,1,1],
[0,0,0,1,1]
]

return 1
Given grid =

[
[1,1,0,1,1],
[1,0,0,0,0],
[0,0,0,0,1],
[1,1,0,1,1]
]

return 3

思路:
类似于求岛屿的个数,但是要存放每个岛屿的位置。对于如何表示可以由位移得到的岛屿,可以令岛屿每个位置都减去其最左和最上的值,得到的数字存入字符串中。可以由位移得到的两个岛屿,其字符串是相同的。

#ifndef C860_H
#define C860_H
#include<iostream>
#include<vector>
#include<map>
#include<algorithm>
#include<string>
#include<set>
using namespace std;
class Solution {
public:
    /**
    * @param grid: a list of lists of integers
    * @return: return an integer, denote the number of distinct islands
    */
    int numberofDistinctIslands(vector<vector<int>> &grid) {
        // write your code here
        if (grid.empty() || grid[0].empty())
            return 0;
        int rows = grid.size();
        int cols = grid[0].size();
        vector<vector<int>> dic{ { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
                map<int, int> visited;
        set<string> island;
        for (int i = 0; i < rows; ++i)
        {
            for (int j = 0; j < cols; ++j)
            {
                if (grid[i][j] == 1 && visited.find(i*cols + j) == visited.end())
                {
                    vector<pair<int, int>> pos;
                    helper(i, j, grid, dic, pos, visited);
                    //可由平移得到的岛屿其字符串是相同的
                    island.insert(build(pos, cols));
                }
            }
        }
        return island.size();
    }
    //对位置(i,j)判断其是否为岛屿,并找到包含它的最大岛屿,位置是否被访问存放在visited中,岛屿的位置存放在pos中
    void helper(int i, int j, vector<vector<int>> &grid, vector<vector<int>> &dic,vector<pair<int,int>> &pos, map<int, int> &visited)
    {
        int rows = grid.size();
        int cols = grid[0].size();
        if (i < 0 || i >= rows || j < 0 || j >= cols)
            return ;
        if (grid[i][j] == 0 || visited[i*cols + j] == 1)
            return ;
        visited[i*cols + j] = 1;
        pos.push_back(make_pair(i,j));
        for (auto c : dic)
        {
            int x = i + c[0];
            int y = j + c[1];
            helper(x, y, grid, dic, pos, visited);
        }
    }
    //对于岛屿,找到其最左left和最上的位置top,用每个位置i,j分别减去left和top
    //得到的i-left和j-top存入字符串
    string build(vector<pair<int,int>> pos, int cols)
    {
        int left = INT_MAX, top = INT_MAX;
        for (auto c : pos)
        {
            if (c.first < left)
                left = c.first;
            if (c.second < top)
                top = c.second;
        }
        sort(pos.begin(), pos.end());
        string str;
        for (auto c : pos)
        {
            str += to_string(c.first - left) + to_string(c.second-top);
        }
        return str;
    }
};
#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值