力扣-Hot100-图论【算法学习day.38】
前言
###我做这类文档一个重要的目的还是给正在学习的大家提供方向(例如想要掌握基础用法,该刷哪些题?)我的解析也不会做的非常详细,只会提供思路和一些关键点,力扣上的大佬们的题解质量是非常非常高滴!!!
习题
1.岛屿数量
题目链接:200. 岛屿数量 - 力扣(LeetCode)
题面:
分析:定义一个递归函数,用于将从某一点开始的四周相邻的1全部标记,然后我们遍历这个二阶数组,如果grid[i][j]==1&&flag[i][j]==0(flag表示标记该点是否属于其他岛屿),就将该点传入递归函数,将同属于该岛屿的所有点打上标记,ans++,最后返回ans即可
代码:
class Solution {
int[][] flag;
char[][] grid;
int n;
int m;
int ans = 0;
public int numIslands(char[][] grid) {
n = grid.length;
m = grid[0].length;
flag = new int[n][m];
this.grid = grid;
for(int i = 0;i<n;i++){
for(int j = 0;j<m;j++){
if(flag[i][j]==0&&grid[i][j]=='1'){
ans++;
recursion(i,j);
}
}
}
return ans;
}
public void recursion(int i,int j){
if(grid[i][j]!='1'||flag[i][j]==1)return;
flag[i][j] = 1;
//上
if(i-1>=0&&flag[i-1][j]==0)recursion(i-1,j);
//下
if(i+1<n&&flag[i+1][j]==0)recursion(i+1,j);
//左
if(j-1>=0&&flag[i][j-1]==0)recursion(i,j-1);
//右
if(j+1<m&&flag[i][j+1]==0)recursion(i,j+1);
}
}
2.腐烂的橘子
题目链接:994. 腐烂的橘子 - 力扣(LeetCode)
题面:
分析:模拟题,我们可以先遍历二维数组,定义两个队列,来存放下一分钟开始向四周腐烂的橘子的行纵坐标, 在额外定义一个遍历来表示新鲜橘子的剩余数量,然后每分钟开始时,我们从队列中取烂橘子,定义一个函数,用来表示一个橘子向四周腐烂的过程,如果将好橘子变成了坏橘子,就将这个新的坏橘子存入队列,并让新鲜橘子减一,当队列中不存在坏橘子时,循环结束,如果仍有好橘子存在,就返回-1,否则返回时间记录变量ans,详细看代码:
代码:
class Solution {
public int orangesRotting(int[][] grid) {
Queue<Integer> qi = new LinkedList<>();
Queue<Integer> qj = new LinkedList<>();
int ans = 0;
int n = grid.length;
int m = grid[0].length;
int freshOrange = 0;
for(int i = 0;i<n;i++){
for(int j = 0;j<m;j++){
if(grid[i][j]==2){
qi.offer(i);
qj.offer(j);
}
else if(grid[i][j]==1){
freshOrange++;
}
}
}
if(freshOrange==0)return 0;
// System.out.println(freshOrange);
// System.out.println(qi.size());
while(!qi.isEmpty()){
ans++;
// System.out.println(freshOrange+" "+qi.size());
int flag = qi.size();
for(int k = 0;k<flag;k++){
int i = qi.poll();
int j = qj.poll();
//上
if(i-1>=0&&grid[i-1][j]==1){
grid[i-1][j]=2;
qi.offer(i-1);
qj.offer(j);
freshOrange--;
}
//下
if(i+1<n&&grid[i+1][j]==1){
grid[i+1][j]=2;
qi.offer(i+1);
qj.offer(j);
freshOrange--;
}
//左
if(j-1>=0&&grid[i][j-1]==1){
grid[i][j-1]=2;
qi.offer(i);
qj.offer(j-1);
freshOrange--;
}
//右
if(j+1<m&&grid[i][j+1]==1){
grid[i][j+1]=2;
qi.offer(i);
qj.offer(j+1);
freshOrange--;
}
}
}
if(freshOrange>0)return -1;
return ans-1;
}
}
3.课程表
题目链接:207. 课程表 - 力扣(LeetCode)
题面:
分析:主要是看有没有成环
代码:
class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
List<Integer>[] g = new ArrayList[numCourses];
Arrays.setAll(g, i -> new ArrayList<>());
for (int[] p : prerequisites) {
g[p[1]].add(p[0]);
}
int[] colors = new int[numCourses];
for (int i = 0; i < numCourses; i++) {
if (colors[i] == 0 && dfs(i, g, colors)) {
return false; // 有环
}
}
return true; // 没有环
}
private boolean dfs(int x, List<Integer>[] g, int[] colors) {
colors[x] = 1; // x 正在访问中
for (int y : g[x]) {
if (colors[y] == 1 || colors[y] == 0 && dfs(y, g, colors)) {
return true; // 找到了环
}
}
colors[x] = 2; // x 完全访问完毕
return false; // 没有找到环
}
}
4.实现前缀Trie
题目链接:208. 实现 Trie (前缀树) - 力扣(LeetCode)
题面:
分析:
1.暴力做法就是把字符串存数组里,判断字符串是否存在就是遍历数组,判断是否以某一字符串作为开头,就是使用startWith函数
2.我们可以定义一个内部类Node,表示节点,他有两个属性,分别是子节点数组和是否是end(为某个单词的最后一个字母),当添加一个单词时,我们从root出发,遍历这个单词,如果某个子节点不存在,就创建这个子节点,查某个单词时,就看遍历时是不是都存在以及是否最后一个节点的end值为true,而查前缀就只需看是否都存在,具体请看下图
代码:
class Node{
Node[] son = new Node[26];
boolean end;
}
class Trie {
Node root;
public Trie() {
root = new Node();
}
public void insert(String word) {
char[] chars = word.toCharArray();
int n = chars.length;
Node node = root;
for(int i = 0;i<n;i++){
int flag = chars[i]-'a';
if(node.son[flag]==null){
node.son[flag] = new Node();
}
node = node.son[flag];
}
node.end = true;
}
public boolean search(String word) {
char[] chars = word.toCharArray();
int n = chars.length;
Node node = root;
for(int i = 0;i<n;i++){
int flag = chars[i]-'a';
if(node.son[flag]==null){
return false;
}
node = node.son[flag];
}
if(node.end)return true;
return false;
}
public boolean startsWith(String prefix) {
char[] chars = prefix.toCharArray();
int n = chars.length;
Node node = root;
for(int i = 0;i<n;i++){
int flag = chars[i]-'a';
if(node.son[flag]==null){
return false;
}
node = node.son[flag];
}
return true;
}
}
/**
* Your Trie object will be instantiated and called as such:
* Trie obj = new Trie();
* obj.insert(word);
* boolean param_2 = obj.search(word);
* boolean param_3 = obj.startsWith(prefix);
*/
后言
上面是力扣Hot100的图论专题,下一篇是其他专题的习题,希望有所帮助,一同进步,共勉!