Leecode热题100中图论章节 200. 岛屿数量 994. 腐烂的橘子 207. 课程表 208. 实现 Trie (前缀树)

本文介绍了LeetCode中涉及的图论问题,包括用DFS解决岛屿数量问题,BFS算法处理腐烂橘子的最短路径,以及使用DFS判断课程表中的环。同时涵盖了Trie(前缀树)的实现方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

200. 岛屿数量

200. 岛屿数量

// 图论  dfs
// leecode题解中nettee的岛屿问题系列通用解法
class Solution {
    public int numIslands(char[][] grid) {
        int res = 0;   // 记录找到的岛屿数量
        for(int i = 0; i < grid.length; i++){
            for(int j = 0; j < grid[0].length; j++){
                // 找到 1 ,res加1,同时淹没这个岛屿
                if(grid[i][j] == '1'){
                    res++;
                    dfs(grid, i, j);
                }
            }
        }
        return res;
    }

    void dfs(int[][] grid, int r, int c) {
        // 判断 base case
        if (!inArea(grid, r, c)) {
            return;
        }
        // 如果这个格子不是岛屿,直接返回
        if (grid[r][c] != 1) {
            return;
        }
        grid[r][c] = 2; // 将格子标记为「已遍历过」
        
        // 访问上、下、左、右四个相邻结点
        dfs(grid, r - 1, c);
        dfs(grid, r + 1, c);
        dfs(grid, r, c - 1);
        dfs(grid, r, c + 1);
    }

    //  判断坐标 (r, c) 是否在网格中
    boolean inArea(int[][] grid, int r, int c) {
        return 0 <= r && r < grid.length 
                && 0 <= c && c < grid[0].length;
    }


}

994. 腐烂的橘子

994. 腐烂的橘子

// leecode题解里nettee的解法
// 求腐烂橘子到所有新鲜橘子的最短路径  使用 BFS
class Solution {
    public int orangesRotting(int[][] grid) {
        Queue<int[]> queue = new LinkedList<>();
        int count = 0;    // 表示新鲜橘子的数量

        for(int i = 0; i < grid.length; i++){
            for(int j = 0; j < grid[0].length; j++){
                if(grid[i][j] == 1){
                    count++;
                }else if(grid[i][j] == 2){
                    queue.add(new int[]{i, j});
                }
            }
        }

        int round = 0; // round表示腐烂的轮数
        while(count > 0 && !queue.isEmpty()){
            round++;
            int n = queue.size();
            for(int i = 0; i < n; i++){
                int[] orange = queue.poll();
                int r = orange[0];
                int c = orange[1];
                if(r - 1 >= 0 && grid[r - 1][c] == 1){
                    grid[r - 1][c] = 2;
                    count--;
                    queue.add(new int[]{r - 1, c});
                }
                if(r + 1 < grid.length && grid[r + 1][c] == 1){
                    grid[r + 1][c] = 2;
                    count--;
                    queue.add(new int[]{r + 1, c});
                }
                if(c - 1 >= 0 && grid[r][c - 1] == 1){
                    grid[r][c - 1] = 2;
                    count--;
                    queue.add(new int[]{r, c - 1});
                }
                if(c + 1 < grid[0].length && grid[r][c + 1] == 1){
                    grid[r][c + 1] = 2;
                    count--;
                    queue.add(new int[]{r, c + 1});
                }                
            }

        }

        if(count > 0){
            return -1;
        }else{
            return round;
        }
    }
}
// 解题思路
// 1. 一开始,我们找出所有腐烂的橘子,将它们放入队列,作为第 0 层的结点。
// 2. 然后进行 BFS 遍历,每个结点的相邻结点可能是上、下、左、右四个方向的结点,注意判断结点位于网格边界的特殊情况。
// 3. 由于可能存在无法被污染的橘子,我们需要记录新鲜橘子的数量。在 BFS 中,每遍历到一个橘子(污染了一个橘子),就将新鲜橘子的数量减一。如果 BFS 结束后这个数量仍未减为零,说明存在无法被污染的橘子。

207. 课程表

207. 课程表
在这里插入图片描述

解题思路

本题可约化为: 判断课程安排图是否是 有向无环图(DAG)
通过DFS判断图中是否有环

// leecode题解中Krahets的DFS解法
class Solution {
   public boolean canFinish(int numCourses, int[][] prerequisites) {
       List<List<Integer>> adjacency = new ArrayList<>();
       for(int i = 0; i < numCourses; i++)
           adjacency.add(new ArrayList<>());
       int[] flags = new int[numCourses];
       for(int[] cp : prerequisites)
           adjacency.get(cp[1]).add(cp[0]);
       for(int i = 0; i < numCourses; i++)
           if(!dfs(adjacency, flags, i)) return false;
       return true;
   }
   private boolean dfs(List<List<Integer>> adjacency, int[] flags, int i) {
       if(flags[i] == 1) return false;
       if(flags[i] == -1) return true;
       flags[i] = 1;
       for(Integer j : adjacency.get(i))
           if(!dfs(adjacency, flags, j)) return false;
       flags[i] = -1;
       return true;
   }
}

208. 实现 Trie (前缀树)

b站视频讲解
Leecode题目链接

26叉树的建立和查询

class Trie {
    // 26个指向下一个节点的指针,如果表示的字母在字符串中有下一个字母,就指向代表下一个字母的node节点
    // 没有 则指向为NULL
    private Trie[] children; 
    private boolean isEnd;  // 表示当前字母是否是某个字符串的结尾

    public Trie() {
        children = new Trie[26];
        isEnd = false;
    }
    
    public void insert(String word) {
        Trie node = this; // 初始化根节点
        for (int i = 0; i < word.length(); i++) {
            char ch = word.charAt(i);
            int index = ch - 'a';
            // 插入节点 先看看当前node是否已经有指向该字母的next指针
            // 如果没有 则新建一个节点
            if (node.children[index] == null) {
                node.children[index] = new Trie();
            }
            // 无论是新建还是已经指向该字母的next指针
            // 当前node移动到该字母节点
            node = node.children[index];
        }
        // 如果此时的字母是插入的字符串的最后一个
        // 标记isEnd为true 表示该字母在某一个字符串里面是结束字母
        node.isEnd = true;
    }
    // 查询就是 从根节点开始能够依次查找字符串中的字母
    // 并且最后一个字母有标记结束,那么就说明之前trie树有记录同样的字符串
    public boolean search(String word) {
        Trie node = searchPrefix(word);
        return node != null && node.isEnd;
    }
    // 查询前缀和查询是否保存有同样的字符串的思路是一样的
    // 唯一的区别在于 查询的字母是不是某个字符串的结尾并不做要求
    public boolean startsWith(String prefix) {
        return searchPrefix(prefix) != null;
    }

    private Trie searchPrefix(String prefix) {
        Trie node = this;
        for (int i = 0; i < prefix.length(); i++) {
            char ch = prefix.charAt(i);
            int index = ch - 'a';
            if (node.children[index] == null) {
                return null;
            }
            node = node.children[index];
        }
        return node;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值