【问题标题】:The program does not give the desired output for input of size greater than 256对于大小大于 256 的输入,该程序没有给出所需的输出
【发布时间】:2021-08-19 05:35:18
【问题描述】:

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

(这是leetcode的问题)

例如-

输入:网格 =

[
  ["1","1","0","0","0"],
  ["1","1","0","0","0"],
  ["0","0","1","0","0"],
  ["0","0","0","1","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, visited, i);
        }
    }
    return ans;
}

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

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

为什么会这样?

【问题讨论】:

  • 它是因为第一个和第二个数据类型是 char 并且它可以达到 255
  • 如果将关键字char 的所有实例都替换为int 会发生什么?
  • char first = '0' + i; - 没有必要把它变成一个字符,甚至根本不需要一个first 变量。只需str += std::to_string(i);。看起来像这样的其他代码行也是如此。
  • char 不需要能够表示大于 255 的值。而且,在大多数实现中,它不需要。 charsigned 还是 unsigned 类型是实现定义的。如果它是signed 类型,则仅保证(按标准)能够表示从-127127 的值,如果它是unsigned 类型,则仅保证能够表示值从0255。如果您需要更大范围的值,请使用可以表示(至少)您需要的范围的类型。

标签: c++ algorithm graph depth-first-search


【解决方案1】:

这是我的方法:

  • 重新格式化输入文件。删除不必要的字符 ([ ] " ,) 并添加文件和行格式标识。对于一个体面的测试编辑器来说,这是一项微不足道的任务 - 我使用 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, col ),
                    orthogonalGridNodeName(row+1, col ),
                    1);
            }
        }
    }
}

最后,作为对所有这些乱七八糟的奖励,两行代码就足以计算岛屿的数量

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

哪个输出:

这个here的完整代码

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

有1个岛屿

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-02
    • 2020-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多