leetcode之深度优先搜索刷题总结2
Posted nuist__NJUPT
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode之深度优先搜索刷题总结2相关的知识,希望对你有一定的参考价值。
leetcode之深度优先搜索刷题总结2
1-课程表
题目链接:题目链接戳这里!!!
思路:将所有的点构成一个有向图,对该图的每个顶点进行搜索,使用vis数组进行标记,如果该顶点为被搜索过,则vis为0,如果被以其他顶点启动的搜索过,则vis为-1,如果被当前顶点为启动点搜索过,vis为1,则说明有环。
AC代码如下:
class Solution
public boolean canFinish(int numCourses, int[][] prerequisites)
List<List<Integer>> edge = new ArrayList<>() ;
for(int i=0; i<numCourses; i++)
edge.add(new ArrayList<>()) ;
int [] vis = new int [numCourses] ;
for(int [] courses : prerequisites)
edge.get(courses[1]).add(courses[0]) ;
for(int i=0; i<numCourses; i++)
if(!dfs(edge,i,vis))
return false ;
return true ;
public boolean dfs(List<List<Integer>> edge, int i, int []vis)
if(vis[i]==1)
return false ;
if(vis[i]==-1)
return true ;
vis[i] = 1 ;
for(int j : edge.get(i))
if(!dfs(edge,j,vis))
return false ;
vis[i] = -1 ;
return true ;
2-课程表II
题目链接:题目链接戳这里!!!
思路:dfs+栈+有向图
构建有向图,vis数组标记三种状态,vis=0,节点未被访问,vis=1,节点在当前dfs中被访问,vis=-1,节点被之前的dfs所访问,dfs判断每个节点,是否有环,有环则返回空数组,否则需要使用stack记录。
class Solution
public int[] findOrder(int numCourses, int[][] prerequisites)
List<List<Integer>> edge = new ArrayList<>() ;
Stack<Integer> stack = new Stack<>() ;
for(int i=0; i<numCourses; i++)
edge.add(new ArrayList<>()) ;
int [] vis = new int [numCourses] ;
for(int [] courses : prerequisites)
edge.get(courses[1]).add(courses[0]) ;
for(int i=0; i<numCourses; i++)
if(!dfs(edge,i,vis,stack))
return new int[] ;
int [] arr = new int [numCourses] ;
int k = 0 ;
while(!stack.isEmpty())
arr[k] = stack.pop() ;
k++ ;
return arr ;
public boolean dfs(List<List<Integer>> edge, int i, int []vis, Stack<Integer>stack)
if(vis[i]==1)
return false ;
if(vis[i]==-1)
return true ;
vis[i] = 1 ;
for(int j : edge.get(i))
if(!dfs(edge,j,vis,stack))
return false ;
vis[i] = -1 ;
stack.push(i) ;
return true ;
3-水壶问题
题目链接:题目链接戳这里!!!
思路1:数学法,贝祖定理。
class Solution
public boolean canMeasureWater(int jug1Capacity, int jug2Capacity, int targetCapacity)
if(jug1Capacity+jug2Capacity<targetCapacity)
return false ;
if(jug2Capacity==0 || jug1Capacity==0)
return targetCapacity==0 || jug2Capacity+jug1Capacity==targetCapacity ;
return targetCapacity % gcd(jug1Capacity,jug2Capacity) == 0 ;
public int gcd(int m, int n)
if(n==0)
return m ;
return gcd(n, m%n) ;
思路2:DFS,用栈模拟
4-字典序排数
题目链接:题目链接戳这里!!!
思路1:用set集合去重和自动排序的功能,当然可以AC,不过效率较低,而且并不是题目要考察的知识点。
class Solution
public List<Integer> lexicalOrder(int n)
Set<String> set = new TreeSet<>() ;
List<Integer> list = new ArrayList<>() ;
for(int i=1; i<=n; i++)
set.add(String.valueOf(i)) ;
for(String s : set)
list.add(Integer.parseInt(s)) ;
return list ;
思路2:把这些数字看成一个字典树,然后通过dfs进行先序遍历就可以了。
class Solution
public List<Integer> lexicalOrder(int n)
List<Integer> list = new ArrayList<>() ;
for(int i=1; i<=9; i++)
dfs(i,n,list) ;
return list ;
public void dfs(int i, int n, List<Integer> list)
if(i>n)
return ;
list.add(i) ;
for(int j=0; j<=9; j++)
dfs(i*10+j,n,list) ;
5-岛屿的周长
题目链接:题目链接戳这里!!!
思路1:只要该位置是陆地就沿着四个方向搜索,如果是边界或者是水域则贡献1,如果当前位置已经搜索过,则贡献0.
class Solution
int [] offsetX = 1,-1,0,0 ;
int [] offsetY = 0,0,-1,1 ;
public int islandPerimeter(int[][] grid)
int cnt = 0 ;
for(int i=0; i<grid.length; i++)
for(int j=0; j<grid[0].length; j++)
if(grid[i][j]==1)
cnt += dfs(grid,i,j) ;
return cnt ;
public int dfs(int [][]grid, int x, int y)
if(x<0 || y<0 || x>grid.length-1 || y>grid[0].length-1 || grid[x][y]==0)
return 1 ;
if(grid[x][y]==2)
return 0 ;
grid[x][y] = 2 ;
int ans = 0 ;
for(int i=0; i<4; i++)
int nx = x + offsetX[i] ;
int ny = y + offsetY[i] ;
ans += dfs(grid,nx,ny) ;
return ans ;
思路2:直接用循环也可以的。如果当前位置是陆地,则当前位置的前后左右四个方向进行判断,如果是边界或者是水域,则当前位置贡献值加1.
class Solution
int [] offsetX = 1,-1,0,0 ;
int [] offsetY = 0,0,-1,1 ;
public int islandPerimeter(int[][] grid)
int ans = 0 ;
for(int i=0; i<grid.length; i++)
for(int j=0; j<grid[0].length; j++)
if(grid[i][j]==1)
int cnt = 0 ;
for(int k=0; k<4; k++)
int nx = i + offsetX[k] ;
int ny = j + offsetY[k] ;
if(nx<0 || ny<0 || nx>grid.length-1 || ny>grid[0].length-1 || grid[nx][ny]==0)
cnt ++ ;
ans += cnt ;
return ans ;
6-甲板上的战舰
题目链接:题目链接戳这里!!!
思路:就是沿着四个方向搜索,判断连通块的数量即可。
每一轮搜索,都把战舰标记为空白,代表搜索过了。
AC代码如下:
class Solution
int [] offsetX = -1,1,0,0 ;
int [] offsetY = 0,0,-1,1 ;
public int countBattleships(char[][] board)
int cnt = 0 ;
for(int i=0; i<board.length; i++)
for(int j=0; j<board[0].length; j++)
if(board[i][j]=='X')
dfs(board,i,j) ;
cnt ++ ;
return cnt ;
public void dfs(char[][]board, int x, int y)
board[x][y] = '.' ;
for(int i=0; i<4; i++)
int tx = x + offsetX[i] ;
int ty = y + offsetY[i] ;
if(tx<0 || ty<0 || tx>board.length-1 || ty>board[0].length-1)
continue ;
if(board[tx][ty]=='X')
dfs(board,tx,ty) ;
7-数组嵌套
题目链接:题目链接戳这里!!!
思路:每一次只要当前值不等于Integer.MAX_VALUE,则循环让下一个下标等于当前值,同时计数加1,同时将Integer.MAX_VALUE赋值给当前值,每轮循环找出最大值即可。
AC代码如下:
class Solution
public int arrayNesting(int[] nums)
int ans = 0 ;
for(int i=0; i<nums.length; i++)
if(nums[i]!=Integer.MAX_VALUE)
int cnt = 0, start = i ;
while(nums[start]!=Integer.MAX_VALUE)
int temp = start ;
start = nums[start] ;
cnt ++ ;
nums[temp] = Integer.MAX_VALUE ;
ans = Math.max(ans, cnt) ;
return ans ;
以上是关于leetcode之深度优先搜索刷题总结2的主要内容,如果未能解决你的问题,请参考以下文章
8-图像渲染
题目链接:题目链接戳这里!!!