对于大小大于 256

问题描述

这是计算网格中岛屿数量代码。给定一个 m x n 二维二进制网格,它表示 '1's(陆地)和 '0's(水域)的地图,返回岛屿的数量。岛被水包围,由水平或垂直连接相邻的陆地而形成。您可以假设网格的所有四个边都被水包围。

(这是来自leetcode的问题)

例如-

输入:网格 =

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

输出:3

限制条件

 - `m == grid.length`
 - `n == grid[i].length`
 - `1 <= m,n <= 300`
 - `grid[i][j] is '0' or '1'.`

我已经通过找到连接组件的总数使用图形解决了这个问题。我使用地图将 (i,j) 对指向其对应的顶点编号,使用邻接列表来存储所有边,并使用访问数组来标记已经访问过的顶点。

代码如下:

void dfs(vector<vector<int>> edges,bool *visited,int start)
{
    visited[start] = true;

    int n = edges[start].size();
    for (int i = 0; i < n; i++)
    {
        if (!visited[edges[start][i]])
            dfs(edges,visited,edges[start][i]);
    }
}

int numIslands(vector<vector<char>> &grid)
{
    int m = grid.size();
    int n = grid[0].size();

    int start = 0;
    unordered_map<string,int> map;

    //storing the ij pair as a string and giving it an integer value to make it a vertex
    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (grid[i][j] == '1')
            {
                char first = '0' + i;
                char second = '0' + j;
                string str = "";
                str += first;
                str += second;
                map[str] = start;
                start++;
            }
        }
    }

    vector<vector<int>> edges(start);

    //adjacency list
    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (grid[i][j] == '1')
            {
                char first = '0' + i;
                char second = '0' + j;
                string str = "";
                str += first;
                str += second;

                if (i - 1 >= 0 && grid[i - 1][j] == '1')
                {
                    char first = '0' + (i - 1);
                    char second = '0' + j;
                    string str1 = "";
                    str1 += first;
                    str1 += second;
                    edges[map[str]].push_back(map[str1]);
                }
                if (i + 1 < m && grid[i + 1][j] == '1')
                {
                    char first = '0' + (i + 1);
                    char second = '0' + j;
                    string str1 = "";
                    str1 += first;
                    str1 += second;
                    edges[map[str]].push_back(map[str1]);
                }
                if (j - 1 >= 0 && grid[i][j - 1] == '1')
                {
                    char first = '0' + i;
                    char second = '0' + (j - 1);
                    string str1 = "";
                    str1 += first;
                    str1 += second;
                    edges[map[str]].push_back(map[str1]);
                }
                if (j + 1 < n && grid[i][j + 1] == '1')
                {
                    char first = '0' + i;
                    char second = '0' + (j + 1);
                    string str1 = "";
                    str1 += first;
                    str1 += second;
                    edges[map[str]].push_back(map[str1]);
                }
            }
        }
    }

    //counting the number of connected components
    bool *visited = new bool[start];
    for (int i = 0; i < start; i++)
        visited[i] = false;
    int ans = 0;
    for (int i = 0; i < edges.size(); i++)
    {
        if (!visited[i])
        {
            ans++;
            dfs(edges,i);
        }
    }
    return ans;
}

代码适用于大多数测试用例。但是,当我输入一行列数大于 256 的输入时,它没有给出所需的输出(即 1)。

例如 - [['1','1',....(287 times) ]] 给出 32 作为输出

为什么会这样?

解决方法

这是我的方法:

  • 重新格式化输入文件。删除不必要的字符 ( [ ] ", ) 并添加文件和行格式标识。对于一个体面的测试编辑器来说,这是一项微不足道的任务 - 我使用 textpad
format islands
o 1 1 0 0 0
o 1 1 0 0 0
o 0 0 1 0 0
o 0 0 0 1 1

读取输入文件的一些代码

   std::vector<std::vector<char>> grid;
    int RowCount = 0;
    int ColCount = -1;
    std::string line;
    while (std::getline(myFile,line))
    {
        std::cout << line << "\n";
        auto token = ParseSpaceDelimited(line);
        if (!token.size())
            continue;
        switch (token[0][0])
        {
        case 'o':
        {
            if (ColCount == -1)
                ColCount = token.size() - 1;
            else if (token.size() - 1 != ColCount)
                throw std::runtime_error("Bad column count");
            std::vector<char> row;
            for (int k = 1; k < token.size(); k++)
                row.push_back(token[k][0]);
            grid.push_back(row);
        }
        break;
        }
    }
    RowCount = grid.size();

一些代码可以在陆地出现的地方添加图形节点。这将 PathFinder C++ wrapper 用于 boost 图库

for (int row = 0; row < RowCount; row++)
{
    for (int col = 0; col < ColCount; col++)
    {
        if (grid[row][col] == '1')
            myFinder.addNode(
                orthogonalGridNodeName(row,col));
    }
}

一些将陆地节点正交链接在一起的代码

for (int row = 0; row < RowCount; row++)
{
    for (int col = 0; col < ColCount; col++)
    {
        int n = row * ColCount + col;

        if (col < ColCount - 1)
        {
            if (grid[row][col] == '1' && grid[row][col + 1] == '1')
            {
                myFinder.addLink(
                    orthogonalGridNodeName(row,col ),orthogonalGridNodeName(row,col + 1 ),1);
            }
        }
        if (row < RowCount - 1)
        {
            if (grid[row][col] == '1' && grid[row + 1][col] == '1')
            {
                myFinder.addLink(
                    orthogonalGridNodeName(row,orthogonalGridNodeName(row+1,1);
            }
        }
    }
}

最后,作为对这一切的奖励,两行代码足以计算岛屿的数量

int cPathFinder::islandCount()
{
    std::vector<int> component(boost::num_vertices(myGraph));
    return boost::connected_components(myGraph,&component[0]);
}

输出:

enter image description here

here的完整代码

顺便说一句,280个左右的1都在一行中给出:

有1个岛屿

enter image description here