题目:Surrounded Regions
给定一个二维矩阵由'x'和'o'表示,其中o被x包围了,如果o上下左右中有其他的o,则被看做是连在一起的,而一起的o中有一个贴边了,就表示这些o都是活的。死的o要替换成x。
思路:
采用广度优先搜索或深度优先搜索来找到连在一起的o;只要遍历过程中有一个贴边的就不在继续搜索,并将现在搜索到的所有活节点全部换成A;
我实际上采用的是广度优先搜索;在搜索过程中未确定的节点我将其转换成了B,最后能判断他的死活时,再转换成对应的标记。
起始外循环是按照从上到下、从左到右的顺序搜索的下面的checkEnclosed函数并不需要再去看它上面的节点或其同一行的右边的点,这些点是判断过得,只有A和X两种可能。
void LeetCode::checkEnclosed(vector<vector<char>>& board, const pair<int, int> cur){ bool flag = false;//标记当前检查的一系列节点是否为活节点 queue<pair<int, int>>Q; vector<pair<int, int>> nodes;//候选节点列表 Q.push(cur); while (!Q.empty()){ pair<int, int> p = Q.front(); //存在上面的节点,此处在solve应用中不需要,因为是从上到下,从左到右,如果存在上面和左面的节点必然是活节点 if (p.first < cur.first || (p.first == cur.first && p.second < cur.second)){ flag = true; break; } if (!p.first || p.first == board.size() - 1 || !p.second || p.second == board.at(0).size() - 1){//在边界上,是活节点 flag = true; break;//以确定死活,不再继续搜索 } //死活暂时未知,要看邻接节点的死活 if (board.at(p.first - 1).at(p.second) == 'A'){ flag = true; break; } else if (board.at(p.first - 1).at(p.second) == 'O'){//存在上边的节点 board.at(p.first - 1).at(p.second) = 'B'; pair<int, int>temp(p.first - 1, p.second); Q.push(temp); } if (board.at(p.first).at(p.second + 1) == 'A'){ flag = true; break; } else if (board.at(p.first).at(p.second + 1) == 'O'){//存在右边的节点 board.at(p.first).at(p.second + 1) = 'B'; pair<int, int>temp(p.first, p.second + 1); Q.push(temp); } if (board.at(p.first + 1).at(p.second) == 'A'){ flag = true; break; } else if (board.at(p.first + 1).at(p.second) == 'O'){//存在下边的节点 board.at(p.first + 1).at(p.second) = 'B'; pair<int, int>temp(p.first + 1, p.second); Q.push(temp); } if (board.at(p.first).at(p.second - 1) == 'A'){ flag = true; break; } else if (board.at(p.first).at(p.second - 1) == 'O'){//存在左边的节点 board.at(p.first).at(p.second - 1) = 'B'; pair<int, int>temp(p.first, p.second - 1); Q.push(temp); } Q.pop(); nodes.push_back(p);//放入候选列表中 } while (!Q.empty()){//将队列中剩余的节点放到候选列表中 pair<int, int> p = Q.front(); Q.pop(); nodes.push_back(p); } if (!flag){//候选列表中的是死节点 auto it = nodes.begin(); while (it != nodes.end()){ board.at((*it).first).at((*it).second) = 'X';//改为死节点 ++it; } } else{ auto it = nodes.begin(); while (it != nodes.end()){ board.at((*it).first).at((*it).second) = 'A';//标记活节点 ++it; } } } void LeetCode::solve(vector<vector<char>>& board){ stack<pair<int, int>>s; for (vector<int>::size_type i = 0; i < board.size(); i++){ for (vector<int>::size_type j = 0; j < board.at(i).size(); j++){ if (board.at(i).at(j) == 'O'){//需要判断死活的子 pair<int, int>temp(i, j); checkEnclosed(board, temp); } } } for (vector<int>::size_type i = 0; i < board.size(); i++){ for (vector<int>::size_type j = 0; j < board.at(i).size(); j++){ if (board.at(i).at(j) == 'A'){//用于标记的活节点 board.at(i).at(j) = 'O'; } } } }
题目:Number of Islands
给定一个二维矩阵由'1'和'0'表示,其中0表示水,1表示岛屿,上下左右相同表示联通,多个1连成一座岛屿;找岛屿的个数。
思路:
和上面类似,广度优先搜索找到所有与当前节点是一个岛屿的点,并将它们都设为2。
int LeetCode::numIslands(vector<vector<char>>& grid){ int count = 0; queue<pair<int, int>>Q;//记录广度优先搜索的节点 for (size_t i = 0; i < grid.size(); ++i){ for (size_t j = 0; j < grid.at(0).size(); ++j){ if (grid.at(i).at(j) == '1'){//需要判断是否是岛 ++count; Q.push(make_pair(i,j)); grid.at(i).at(j) = '2'; while (!Q.empty()){ auto p = Q.front(); Q.pop(); if (p.first > 0 && grid.at(p.first - 1).at(p.second) == '1'){ Q.push(make_pair(p.first - 1, p.second));//左边 grid.at(p.first - 1).at(p.second) = '2';//立即设为2,防止重复添加 } if (p.second > 0 && grid.at(p.first).at(p.second - 1) == '1'){ Q.push(make_pair(p.first, p.second - 1));//上边 grid.at(p.first).at(p.second - 1) = '2'; } if (p.first < grid.size() - 1 && grid.at(p.first + 1).at(p.second) == '1'){ Q.push(make_pair(p.first + 1, p.second));//右边 grid.at(p.first + 1).at(p.second) = '2'; } if (p.second < grid.at(0).size() - 1 && grid.at(p.first).at(p.second + 1) == '1'){ Q.push(make_pair(p.first, p.second + 1));//下边 grid.at(p.first).at(p.second + 1) = '2'; } } } } } for (size_t i = 0; i < grid.size(); ++i){ for (size_t j = 0; j < grid.at(0).size(); ++j){ if (grid.at(i).at(j) == '2'){//将2还原为1 grid.at(i).at(j) = '1'; } } } return count; }
下面是深度优先搜索的实现
int LeetCode::numIslands(vector<vector<char>>& grid){ int count = 0; stack<pair<int, int>>s;//记录深度优先搜索的节点 for (size_t i = 0; i < grid.size(); ++i){ for (size_t j = 0; j < grid.at(0).size(); ++j){ if (grid.at(i).at(j) == '1'){//需要判断是否是岛 ++count; s.push(make_pair(i, j)); grid.at(i).at(j) = '2'; while (!s.empty()){ auto p = s.top(); if (p.first > 0 && grid.at(p.first - 1).at(p.second) == '1'){ s.push(make_pair(p.first - 1, p.second));//左边 grid.at(p.first - 1).at(p.second) = '2';//立即设为2,防止重复添加 }else if (p.second > 0 && grid.at(p.first).at(p.second - 1) == '1'){ s.push(make_pair(p.first, p.second - 1));//上边 grid.at(p.first).at(p.second - 1) = '2'; }else if (p.first < grid.size() - 1 && grid.at(p.first + 1).at(p.second) == '1'){ s.push(make_pair(p.first + 1, p.second));//右边 grid.at(p.first + 1).at(p.second) = '2'; }else if (p.second < grid.at(0).size() - 1 && grid.at(p.first).at(p.second + 1) == '1'){ s.push(make_pair(p.first, p.second + 1));//下边 grid.at(p.first).at(p.second + 1) = '2'; } else{//回溯 s.pop(); } } } } } for (size_t i = 0; i < grid.size(); ++i){ for (size_t j = 0; j < grid.at(0).size(); ++j){ if (grid.at(i).at(j) == '2'){//将2还原为1 grid.at(i).at(j) = '1'; } } } return count; }