JAVA算法练习题day43
图论
图论的DFS:1.搜索方向:认准一个方向搜,直到碰壁之后再换方向;2.换方向是撤销原路径,改为节点链接的下一个路径,回溯的过程。【用递归最方便】
解决了究极疑惑:偏移量和坐标轴的问题。
代码:
int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1}; // 表示四个方向
// grid 是地图,也就是一个二维数组
// visited标记访问过的节点,不要重复访问
// x,y 表示开始搜索节点的下标
void bfs(vector<vector<char>>& grid, vector<vector<bool>>& visited, int x, int y) {queue<pair<int, int>> que; // 定义队列que.push({x, y}); // 起始节点加入队列visited[x][y] = true; // 只要加入队列,立刻标记为访问过的节点while(!que.empty()) { // 开始遍历队列里的元素pair<int ,int> cur = que.front(); que.pop(); // 从队列取元素int curx = cur.first;int cury = cur.second; // 当前节点坐标for (int i = 0; i < 4; i++) { // 开始想当前节点的四个方向左右上下去遍历int nextx = curx + dir[i][0];int nexty = cury + dir[i][1]; // 获取周边四个方向的坐标if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue; // 坐标越界了,直接跳过if (!visited[nextx][nexty]) { // 如果节点没被访问过que.push({nextx, nexty}); // 队列添加该节点为下一轮要遍历的节点visited[nextx][nexty] = true; // 只要加入队列立刻标记,避免重复访问}}}
为什么是这个遍历顺序呢?
看二维数组就懂了,二维数组就是我们的坐标系!
51.岛屿数量
DFS方法:
思路没打开:想的是遍历到1之后,怎么去搜这个1的所有满足条件的0,又怎么进一步统计岛屿数量。其实应该:遍历到矩阵的1(岛屿数量++),就开始朝4周对这个1进行深度搜索,直至找到0,这样一来,原1所在的岛屿中的1,我们就搜过了。为了避免重复搜,还要把搜过的1置0。
class Solution(object):def numIslands(self, grid):""":type grid: List[List[str]]:rtype: int"""def dfs(gird,r,c):if r<0 or r>len(grid)-1 or c<0 or c>=len(grid[0]) or gird[r][c]=='0':return#如果置0操作不在DFS函数里面写就会死循环。因为网络结构的特点,遍历过程中就是会有重复的。各个重复的1在互相对彼此做深度搜索,所以死循环了。grid[r][c]='0'dfs(gird,r+1,c)dfs(grid,r-1,c)dfs(grid,r,c+1)dfs(grid,r,c-1)count = 0for r in range(len(grid)):for c in range(len(grid[0])):if grid[r][c]=='1':dfs(grid,r,c)count +=1return count
BFS方法:PYTHON队列这样写入队操作太方便了。
class Solution:def numIslands(self, grid: [[str]]) -> int:def bfs(grid, i, j):queue = [[i, j]]while queue:[i, j] = queue.pop(0)if 0 <= i < len(grid) and 0 <= j < len(grid[0]) and grid[i][j] == '1':grid[i][j] = '0'queue += [[i + 1, j], [i - 1, j], [i, j - 1], [i, j + 1]]count = 0for i in range(len(grid)):for j in range(len(grid[0])):if grid[i][j] == '0': continuebfs(grid, i, j)count += 1return count