代码随想录 —— Hot100【二刷】

207. 课程表

算法思想:能否排拓扑排序的题目。若有向图不构成环,则能有拓扑序。每遍历一个课程,都需先遍历其前导课程。只有前导课程都成拓扑序,考虑当前课程,才能成拓扑序。
判断成环技巧:在递归过程,将课程用 visited = 2 表示正在等待其前导课程的拓扑序。若图中有环,必定从某个点出发,有会回到某个点,因此会出现其前导课程 visited = 2 的情况,此时返回 false。若前导课程为visited = 1 ,说明前导课程已成拓扑序,直接返回 true即可。若当前课程的所有前导课程已成拓扑序,则将当前课程的visited = 1

class Solution {
public:
    vector<int> visited;
    vector<vector<int>> adj;
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        visited.resize(numCourses,0);
        adj.resize(numCourses); 
        for (auto &vec : prerequisites) {
            int curCol = vec[0];
            int preCol = vec[1];
            adj[curCol].emplace_back(preCol);
        }
        bool flag;
        for (int i=0; i<numCourses; ++i) {
            if (!visited[i]) {
                flag = dfs(i);
                if (!flag)
                    return false;
            }
        }
        return true;
    }

    bool dfs(int curCol) {
        // 若某课程与先导课程成环,说明肯定不存在拓扑结构
        if (visited[curCol] == 2)
            return false;
        // 若当前课程与其先导课程已经排好拓扑序
        if (visited[curCol] == 1)
            return true;
        visited[curCol] = 2;
        bool flag;
        // 若其先导课程均能成拓扑序
        for (auto &data : adj[curCol]) {
            flag = dfs(data);
            if (!flag)
                return false;
        }
        visited[curCol] = 1;
        return true;
    }
};

208. 实现 Trie (前缀树)【重做!!】

insert()、search()、startsWith() 三个操作都是令指针从前缀树自上而下按字符位置遍历,所不同的是根据不同条件作出不同的行为。
· insert():若当前字符不在前缀树,则创建对象,并指向它,因此我们是使用往前探索判断的策略:ptr->vec[ch-'a']
· search():若在遍历过程中不存在字符,则返回 false;若遍历结束,还要判断当前是否有 hasWord 标志,若无,说明,word 在当前词组中只充当前缀
· startsWith():相比 search(),只是少了判断 hasWord 标志的过程。

class Trie {
public:
    vector<Trie*> vec;
    bool hasWord;
    Trie() {
        vec.resize(26, nullptr);
        hasWord = false;
    }
    
    void insert(string word) {
        Trie* ptr = this;
        for (auto &ch : word) {
            if (!ptr->vec[ch-'a'])
                ptr->vec[ch-'a'] = new Trie();
            ptr = ptr->vec[ch-'a'];
        }
        ptr->hasWord = true;
    }
    
    bool search(string word) {
        Trie* ptr = this;
        for (auto &ch : word) {
            if (!ptr->vec[ch-'a'])
                return false;
            ptr = ptr->vec[ch-'a'];
        }
        return ptr->hasWord;
    }
    
    bool startsWith(string prefix) {
        Trie* ptr = this;
        for (auto &ch : prefix) {
            if (!ptr->vec[ch-'a'])
                return false;
            ptr = ptr->vec[ch-'a'];
        }
        return true;
    }
 
};

221. 最大正方形

备注:当初直接在 matrix 上对字符进行加减操作,这样会出错。因为会超出 ASCII 码的表示返回,会取余。正确做法是,另开 vector<vector> 的 dp 数组。

class Solution {
public:
    int maximalSquare(vector<vector<char>>& matrix) {
        int maxEdge = 0;
        int m = matrix.size(), n = matrix[0].size();
        vector<vector<int>> dp(m, vector<int>(n, 0));
        for (int i=0; i<m; ++i) {
            for (int j=0; j<n; ++j) {
                if (matrix[i][j] == '0')
                    dp[i][j] = 0;
                else {
                    dp[i][j] = 1;
                    maxEdge = 1;
                }
            }
        }

        for (int i=1; i<m; ++i) {
            for (int j=1; j<n; ++j) {
                if (dp[i][j] == 0)
                    continue;
                int minVal = min(dp[i-1][j], dp[i][j-1]);
                minVal = min(minVal, dp[i-1][j-1]);
                dp[i][j] = minVal + 1;
                maxEdge = max(dp[i][j], maxEdge);
            }
        }
        return maxEdge * maxEdge;
    }
};
posted @ 2022-08-28 10:11  MasterBean  阅读(71)  评论(0)    收藏  举报