【LeetCode 热题 100】图论 专题(bfs,拓扑排序,Trie树 字典树)

from: https://leetcode.cn/studyplan/top-100-liked/

bfs 具有 边权为1 的最短路性质

拓扑排序,入度

Trie树, 高效存储 字符串【见鬼,不知道为什么写错,需要掌握熟练度】


文章目录

    • [200. 岛屿数量【dfs / bfs】](#200. 岛屿数量【dfs / bfs】)
    • [994. 腐烂的橘子【bfs 具有 边权为1 的最短路性质】](#994. 腐烂的橘子【bfs 具有 边权为1 的最短路性质】)
    • [207. 课程表【拓扑排序】](#207. 课程表【拓扑排序】)
    • [208. 实现 Trie (前缀树)【模板题】](#208. 实现 Trie (前缀树)【模板题】)

200. 岛屿数量【dfs / bfs】

dfs 写法,比较简洁

c++ 复制代码
class Solution {
public:

    int dx[4] = {-1,0,1,0}, dy[4] = {0,1,0,-1};
    int n, m;

    int numIslands(vector<vector<char>>& grid) {
        n = grid.size(), m = grid[0].size();
   
        int cnt = 0;
        for(int i = 0;i < n;i ++ ){
            for(int j = 0;j < m;j ++ ){
                if(grid[i][j] == '1') {
                    cnt ++ ;
                    dfs(i, j, grid);
                }
            }
        }
        return cnt;
    }

    void dfs(int x, int y,vector<vector<char>>& grid){
        grid[x][y] = '0';
        for(int i = 0;i < 4;i ++ ){
            int a = x + dx[i], b = y + dy[i];
            if(a >= 0 && a < n && b >= 0 && b < m && grid[a][b] == '1') 
                dfs(a, b, grid);
        }
    };
};

bfs 写法,有最短路性质

c++ 复制代码
#define x first
#define y second

class Solution {
public:
    int n, m;
    typedef pair<int,int> PII;
    int dx[4] = {-1,0,1,0}, dy[4] = {0,1,0,-1};

    int numIslands(vector<vector<char>>& grid) {
        if(grid.empty() || grid[0].empty()) return 0;

        n = grid.size(), m = grid[0].size();

        int res = 0;
        for(int i =0;i<n;i++)
            for(int j=0;j<m;j++)
                if(grid[i][j] == '1')
                {
                    res ++;
                    bfs(i,j,grid);
                   
                }
        
        return res;
    }

    void bfs(int x,int y,vector<vector<char>>& grid)
    {
        queue<PII> q;
        q.push({x,y});
        grid[x][y] = '0';

        while(!q.empty())
        {
            auto t = q.front();
            q.pop();


            for(int i=0;i<4;i++)
            {
                int a = t.x + dx[i], b =t.y + dy[i]; // debug : 这里是新坐标的t.x 不是 x
                if(a >= 0 && a < n && b >= 0 && b < m && grid[a][b] == '1')
                {
                    grid[a][b] = '0';
                    q.push({a,b});
                }
            }
        }
    }
};

994. 腐烂的橘子【bfs 具有 边权为1 的最短路性质】

bfs 具有 边权为1 的最短路性质

c++ 复制代码
class Solution {
public:
    int orangesRotting(vector<vector<int>>& grid) {
        int n = grid.size(), m = grid[0].size();
        
        bool st[n][m];
        memset(st, 0, sizeof st);

        queue<pair<int,int>> q;
        int dx[4] = {-1,0,1,0}, dy[4] = {0,1,0,-1};

        for(int i = 0;i < n;i ++ ){
            for(int j = 0; j < m;j ++ ){
                if(grid[i][j] == 2) {
                    q.push({i, j});
                    st[i][j] = true;
                }
            }
        }

        int res = 0;
        while(q.size()){
            
            int k = q.size(); // debug: int k, 写成n 和 前面命名重复了!
            res ++ ;
            while(k -- ){
                auto t = q.front();
                q.pop();
                
                for(int i = 0;i < 4;i ++ ){
                    int a = t.first + dx[i], b = t.second + dy[i];
                    if(a >= 0 && a < n && b >= 0 && b < m && grid[a][b] == 1 && !st[a][b]){
                        q.push({a, b});
                        grid[a][b] = 2;
                        st[a][b] = true;
                    }
                }
            }
            
        }

        for(int i = 0;i < n;i ++ ){
            for(int j = 0; j < m;j ++ ){
                if(grid[i][j] == 1) {
                    return -1;
                }
            }
        }
        if(res == 0) return 0;
        return res - 1;
    }
};

207. 课程表【拓扑排序】

拓扑排序

c++ 复制代码
class Solution {
public:
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        // 拓扑排序

        int d[numCourses];
        memset(d, 0, sizeof d);

        vector<int> g[numCourses];


        for(auto &c : prerequisites) {
            int a = c[0], b = c[1];
            g[a].push_back(b);
            d[b] ++ ;
        }

        queue<int> q;
        for(int i = 0;i < numCourses;i ++ ){
            if(d[i] == 0) q.push(i);
        }

        while(q.size()){
            int t = q.front();
            q.pop();

            for(auto to : g[t]){
                    d[to] -- ;
                    if(d[to] == 0) q.push(to);
            }
        }

        for(int i = 0;i < numCourses;i ++ ){
            if(d[i] != 0) return false;
        }
        return true;
    }
};

208. 实现 Trie (前缀树)【模板题】

模板题

数组写法,简洁,需要注意开的数组空间 N * 结点

c++ 复制代码
const int N = 30010;

int tr[N * 26][26], idx;
int cnt[N * 26];

class Trie {
public:
    Trie() {
        idx = 0;
        memset(tr, 0, sizeof tr);
        memset(cnt, 0, sizeof cnt);
    }
    
    void insert(string word) {
        int p = 0;
        for(auto c : word){
            int u = c - 'a';
            if(!tr[p][u]) tr[p][u] = ++ idx;
            p = tr[p][u];
        }
        cnt[p] ++ ;
    }
    
    bool search(string word) {
        int p = 0;
        for(auto c : word){
            int u = c - 'a';
            if(!tr[p][u]) return false;
            p = tr[p][u];
        }
        return cnt[p] > 0;
    }
    
    bool startsWith(string prefix) {
        int p = 0;
        for(auto c : prefix){
            int u = c - 'a';
            if(!tr[p][u]) return false;
            p = tr[p][u];
        }
        return true;
    }
};

/**
 * Your Trie object will be instantiated and called as such:
 * Trie* obj = new Trie();
 * obj->insert(word);
 * bool param_2 = obj->search(word);
 * bool param_3 = obj->startsWith(prefix);
 */

指针写法

c++ 复制代码
class Trie {
public:


    struct Node
    {
        bool is_end;
        Node *son[26];

        Node()
        {
            is_end = false;
            for(int i=0;i<26;i++) son[i] = NULL;
        }
    }*root;


    /** Initialize your data structure here. */
    Trie() {
        root = new Node();
    }
    
    /** Inserts a word into the trie. */
    void insert(string word) {
        auto *p = root;
        for(auto c : word)
        {
            int u = c - 'a';
            if(p->son[u] == NULL) p->son[u] = new Node();
            p = p->son[u];
        }
        p->is_end = true;
    }
    
    /** Returns if the word is in the trie. */
    bool search(string word) {
        auto *p = root;
        for(auto c : word)
        {
            int u = c - 'a';
            if(p->son[u] == NULL) return false;
            p = p->son[u];
        }
        return p->is_end;
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(string prefix) {
        auto *p = root;
        for(auto c : prefix)
        {
            int u = c - 'a';
            if(p->son[u] == NULL) return false;
            p = p->son[u]; 
        }
        return true;
    }
};

/**
 * Your Trie object will be instantiated and called as such:
 * Trie* obj = new Trie();
 * obj->insert(word);
 * bool param_2 = obj->search(word);
 * bool param_3 = obj->startsWith(prefix);
 */
相关推荐
九圣残炎8 分钟前
【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目
java·算法·leetcode
~yY…s<#>2 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode
linsa_pursuer3 小时前
快乐数算法
算法·leetcode·职场和发展
XuanRanDev3 小时前
【每日一题】LeetCode - 三数之和
数据结构·算法·leetcode·1024程序员节
代码猪猪傻瓜coding3 小时前
力扣1 两数之和
数据结构·算法·leetcode
南宫生4 小时前
贪心算法习题其三【力扣】【算法学习day.20】
java·数据结构·学习·算法·leetcode·贪心算法
JingHongB5 小时前
代码随想录算法训练营Day55 | 图论理论基础、深度优先搜索理论基础、卡玛网 98.所有可达路径、797. 所有可能的路径、广度优先搜索理论基础
算法·深度优先·图论
weixin_432702265 小时前
代码随想录算法训练营第五十五天|图论理论基础
数据结构·python·算法·深度优先·图论
小冉在学习5 小时前
day52 图论章节刷题Part04(110.字符串接龙、105.有向图的完全可达性、106.岛屿的周长 )
算法·深度优先·图论
小冉在学习5 小时前
day53 图论章节刷题Part05(并查集理论基础、寻找存在的路径)
java·算法·图论