DFS
leetcode-79-mid
给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例:
board =
[
[‘A’,‘B’,‘C’,‘E’],
[‘S’,‘F’,‘C’,‘S’],
[‘A’,‘D’,‘E’,‘E’]
]
给定 word = “ABCCED”, 返回 true
给定 word = “SEE”, 返回 true
给定 word = “ABCB”, 返回 false
题解
class Solution {
int[][] directions = {{-1,0},{1,0},{0,-1},{0,1}};
public boolean dfs(char[][] board,String word,int pos,int pos1,int pos2,int[][] vis)
{
if (pos == word.length() - 1) {
return board[pos1][pos2] == word.charAt(pos);
}
if(board[pos1][pos2] == word.charAt(pos))
{
vis[pos1][pos2] = 1;
for(int i=0;i<4;i++) // 四个方向走,只要有一个方向是真的,那么就是真的
{
int[] temp = directions[i];
//下一次考虑的坐标要不越界,而且没被访问过
if(pos1+temp[0]>=0 && pos1+temp[0]<board.length && pos2+temp[1]>=0 && pos2+temp[1]<board[0].length && vis[pos1+temp[0]][pos2+temp[1]] == 0)
// 四个方向走,只要有一个方向是真的,那么就是真的
if(dfs(board,word,pos+1,pos1+temp[0],pos2+temp[1],vis))
return true;
}
vis[pos1][pos2] = 0; // 回溯
}
return false;
}
public boolean exist(char[][] board, String word)
{
int rows = board.length;
int cols = board[0].length;
for(int i=0;i<rows;i++)
{
for(int j = 0;j<cols;j++)
{
if(word.charAt(0) == board[i][j])
{
int[][] vis = new int[rows][cols];
if(dfs(board,word,0,i,j,vis)==true)
return true;
}
}
}
return false;
}
}
leetcode-46-全排列
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
题解
class Solution {
List<List<Integer>> res = new ArrayList();
List<Integer> list = new ArrayList();
public void dfs(int[] nums,int step,int[] vis)
{
if(step == nums.length)
res.add(new ArrayList(list));
for(int i=0;i<nums.length;i++)
{
if(vis[i] == 0)
{
vis[i] = 1;
//temp[step] = nums[i];
list.add(nums[i]);
dfs(nums,step+1,vis);
vis[i] = 0;
list.remove(list.size()-1);
}
}
}
public List<List<Integer>> permute(int[] nums)
{
int[] temp = new int[nums.length];
int[] vis = new int[nums.length];
dfs(nums,0,vis);
return res;
}
}
leetcode-695-岛屿的最大面积
给定一个包含了一些 0 和 1 的非空二维数组 grid 。
一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。
找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为 0 。)
示例 1:
[[0,0,1,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,1,1,0,1,0,0,0,0,0,0,0,0],
[0,1,0,0,1,1,0,0,1,0,1,0,0],
[0,1,0,0,1,1,0,0,1,1,1,0,0],
[0,0,0,0,0,0,0,0,0,0,1,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,0,0,0,0,0,0,1,1,0,0,0,0]]
对于上面这个给定矩阵应返回 6。注意答案不应该是 11 ,因为岛屿只能包含水平或垂直的四个方向的 1 。
示例 2:
[[0,0,0,0,0,0,0,0]]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/max-area-of-island
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
class Solution
{
int max = Integer.MIN_VALUE;
int count = 0;
public void getMax(int pos1,int pos2,int[][] vis,int[][]grid)
{
//递归终止条件
if(pos1<0 || pos1>=vis.length || pos2<0 || pos2>=vis[0].length || vis[pos1][pos2]==1)
return;
if(grid[pos1][pos2]==0)
{
vis[pos1][pos2] = 1;
return;
}
//做到这里说明grid[pos1][pos2]==1,访问这个位置,设置vis[pos1][pos2] = 1
vis[pos1][pos2] = 1;
count++;
getMax(pos1-1,pos2,vis,grid); //上下左右进行扫描
getMax(pos1+1,pos2,vis,grid);
getMax(pos1,pos2-1,vis,grid);
getMax(pos1,pos2+1,vis,grid);
if(count>max)
max = count;
}
public int maxAreaOfIsland(int[][] grid)
{
int rows = grid.length;
int cols = grid[0].length;
int[][] vis = new int[rows][cols];
for(int i=0;i<rows;i++) //遍历所有的位置
{
for(int j=0;j<cols;j++)
{
count = 0;
getMax(i,j,vis,grid);
}
}
if(max == Integer.MIN_VALUE)
return 0;
return max;
}
}
leetcode-200-岛屿数量
给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
示例 1:
输入:
11110
11010
11000
00000
输出: 1
示例 2:
输入:
11000
11000
00100
00011
输出: 3
解释: 每座岛屿只能由水平和/或竖直方向上相邻的陆地连接而成。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-islands
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解(根据上一题稍微修改下即可)
class Solution
{
int max = Integer.MIN_VALUE;
void getMax(int pos1,int pos2,int[][] vis,char[][]grid)
{
//递归终止条件
if(pos1<0 || pos1>=vis.length || pos2<0 || pos2>=vis[0].length || vis[pos1][pos2]==1)
return;
if(grid[pos1][pos2]=='0')
{
vis[pos1][pos2] = 1;
return;
}
//做到这里说明grid[pos1][pos2]==1,访问这个位置,设置vis[pos1][pos2] = 1
vis[pos1][pos2] = 1;
getMax(pos1-1,pos2,vis,grid); //上下左右进行扫描
getMax(pos1+1,pos2,vis,grid);
getMax(pos1,pos2-1,vis,grid);
getMax(pos1,pos2+1,vis,grid);
max++;
}
public int numIslands(char[][] grid)
{
int rows = grid.length;
if(rows == 0)
return 0;
int cols = grid[0].length;
int[][] vis = new int[rows][cols];
int count = 0;
for(int i=0;i<rows;i++) //遍历所有的位置
{
for(int j=0;j<cols;j++)
{
max = Integer.MIN_VALUE;
getMax(i,j,vis,grid);
if(max != Integer.MIN_VALUE)
count++;
}
}
return count;
}
}
leetcode-547-朋友圈
题目描述
班上有 N 名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C 的朋友。所谓的朋友圈,是指所有朋友的集合。
给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。
示例 1:
输入:
[[1,1,0],
[1,1,0],
[0,0,1]]
输出: 2
说明:已知学生0和学生1互为朋友,他们在一个朋友圈。
第2个学生自己在一个朋友圈。所以返回2。
示例 2:
输入:
[[1,1,0],
[1,1,1],
[0,1,1]]
输出: 1
说明:已知学生0和学生1互为朋友,学生1和学生2互为朋友,所以学生0和学生2也是朋友,所以他们三个在一个朋友圈,返回1。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/friend-circles
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
class Solution
{
int count = 0;
HashSet set = new HashSet();
int rows;
int cols;
int flag = 0;
void dfs(int key,int[][] M)
{
if(!set.contains(key))
{
if(flag == 0)
count++;
set.add(key);
flag = 1;
for(int i=0;i<rows;i++)
{
//flag = 1;
if(M[key][i]==1)
dfs(i,M);
}
}
else
{
return;
}
}
public int findCircleNum(int[][] M)
{
this.rows = M.length;
this.cols = M[0].length;
int[][] vis = new int[rows][cols];
for(int i=0;i<rows;i++)
{
flag = 0;
dfs(i,M);
}
return count;
}
}
leetcode-130-被围绕的区域
给定一个二维的矩阵,包含 ‘X’ 和 ‘O’(字母 O)。
找到所有被 ‘X’ 围绕的区域,并将这些区域里所有的 ‘O’ 用 ‘X’ 填充。
示例:
X X X X
X O O X
X X O X
X O X X
运行你的函数后,矩阵变为:
X X X X
X X X X
X X X X
X O X X
解释:
被围绕的区间不会存在于边界上,换句话说,任何边界上的 ‘O’ 都不会被填充为 ‘X’。 任何不在边界上,或不与边界上的 ‘O’ 相连的 ‘O’ 最终都会被填充为 ‘X’。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/surrounded-regions
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
class Location //坐标类
{
int pos1;
int pos2;
}
class Solution {
HashSet set = new HashSet();
boolean flag = true; //标志位,看Set中的位置是否可以被改写成"X".
void dfs(char[][] board,int pos1,int pos2,HashSet set,int[][] vis)
{
if(pos1<0 || pos1>=board.length || pos2<0 || pos2>=board[0].length || vis[pos1][pos2] == 1 || board[pos1][pos2] == 'X' ) //如果被遍历过或者该位置为X则return
return;
if((pos1 == 0 || pos1 == board.length-1 || pos2==0 || pos2 == board[0].length-1) && board[pos1][pos2] == 'O') // 如果在边缘处且那位置为‘O’,则flag标记为false,表示Set中元素不可以被改成‘X’。
{
flag = false;
return;
}
if(board[pos1][pos2] == 'O') //如果位置为“O”,则把它加入到Set中。
{
Location location = new Location();
location.pos1 = pos1;
location.pos2 = pos2;
set.add(location);
vis[pos1][pos2] = 1;
}
dfs(board,pos1-1,pos2,set,vis); //递归上下左右四个位置
dfs(board,pos1+1,pos2,set,vis);
dfs(board,pos1,pos2-1,set,vis);
dfs(board,pos1,pos2+1,set,vis);
}
public void solve(char[][] board)
{
if(board.length<=1)
return;
int rows = board.length;
int cols = board[0].length;
if(cols<=1)
return;
for(int i=1;i<rows-1;i++)
{
for(int j=1;j<cols-1;j++)
{
flag = true;
int[][] vis = new int[rows][cols];
HashSet set = new HashSet();
dfs(board,i,j,set,vis);
if(flag == false)
continue;
else
{
Iterator iterator = set.iterator();
while (iterator.hasNext())
{
Location next = (Location)iterator.next();
int s1 = next.pos1;
int s2 = next.pos2;
board[s1][s2] = 'X';
}
set.clear();
}
}
}
}
}