首页 > 其他分享 >Leetcode(剑指offer专项训练)——DFS/BFS专项(2)

Leetcode(剑指offer专项训练)——DFS/BFS专项(2)

时间:2023-04-09 17:13:59浏览次数:49  
标签:专项 顺序 offer int indegree 字母 DFS vector 排序

课程顺序

题目

现在总共有 numCourses 门课需要选,记为 0 到 numCourses-1。
给定一个数组 prerequisites ,它的每一个元素 prerequisites[i] 表示两门课程之间的先修顺序。 例如 prerequisites[i] = [ai, bi] 表示想要学习课程 ai ,需要先完成课程 bi 。
请根据给出的总课程数  numCourses 和表示先修顺序的 prerequisites 得出一个可行的修课序列。
可能会有多个正确的顺序,只要任意返回一种就可以了。如果不可能完成所有课程,返回一个空数组。
链接

拓扑排序题解

思路:很经典的拓扑排序题目了,记录课程的依赖关系为入度和出度,BFS遍历得到拓扑排序序列,判断序列长度是否==所有课程数目,是则给返回拓扑排序结果,否则返回空数组

class Solution {
public:
    vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
        //拓扑排序
        vector<int>indegree(numCourses,0);
        vector<vector<int>>outnodes(numCourses);
        for(auto courses: prerequisites){
            indegree[courses[0]]++;//修0需要先修1 
            outnodes[courses[1]].emplace_back(courses[0]);
        }
        queue<int>q;
        for(int i=0;i<numCourses;i++){
            if(indegree[i]==0){
                q.push(i);
            }
        }
        vector<int>ans;
        while(!q.empty()){
            int size=q.size();
            for(int i=0;i<size;i++){
                int u=q.front();
                q.pop();
                ans.emplace_back(u);
                for(auto v:outnodes[u]){
                    indegree[v]--;
                    if(indegree[v]==0){
                        q.push(v);
                    }
                }
            }
        }
        if(ans.size()!=numCourses){
            return {};
        }
        return ans;
    }
};

外星文字典

题目

现有一种使用英语字母的外星文语言,这门语言的字母顺序与英语顺序不同。
给定一个字符串列表 words ,作为这门语言的词典,words 中的字符串已经 按这门新语言的字母顺序进行了排序 。
请你根据该词典还原出此语言中已知的字母顺序,并 按字母递增顺序 排列。若不存在合法字母顺序,返回 "" 。若存在多种可能的合法字母顺序,返回其中 任意一种 顺序即可。
字符串 s 字典顺序小于 字符串 t 有两种情况:
在第一个不同字母处,如果 s 中的字母在这门外星语言的字母顺序中位于 t 中字母之前,那么 s 的字典顺序小于 t 。
如果前面 min(s.length, t.length) 字母都相同,那么 s.length < t.length 时,s 的字典顺序也小于 t 。
链接

拓扑排序题解

思路:本质上和上一题一样,但是需要自己构建有向图;
需要注意的主要是特判的情况:

  1. 当出现字典中["abc","ab"]的时候,明显字典本身语法有问题,返回""
  2. 当出现回路比如["x","z","x"],在构建的graph中即存在graph[i][j]graph[i][j]同时为'true',即双向箭头,明显不合理,返""
  3. 回路的另一个判别为indegree<0,说明反复走回来一个节点,返回""
class Solution {
public:
    string alienOrder(vector<string>& words) {
        //根据这个词典构建一个入度和出度表,最后给出拓扑排序的序列
        int n=words.size();
        vector<int>indegree(26,-1);
        vector<vector<char>>outnodes(26);
        //初始化
        int cnt=0;
        for(int i=0;i<n;i++){
            for(auto w:words[i]){
                if(indegree[w-'a']!=0){
                    cnt++;
                    indegree[w-'a']=0;
                }
            }
        }
        //构建先后关系的图
        vector<vector<bool>>graph(26,vector<bool>(26,false));
        for(int i=0;i<n-1;i++){
            for(int j=i+1;j<n;j++){
                bool flag=false;
                for(int k=0;k<min(words[i].length(),words[j].length());k++){
                    if(words[i][k]!=words[j][k]){
                        graph[words[i][k]-'a'][words[j][k]-'a']=true;
                        flag=true;
                        break;
                    }
                }
                if(flag){
                    break;
                }else if(words[i].length()>words[j].length()){//特判:字典中比如"abc","ab"这种序列表明自带语法错误
                    return "";
                }
            }
        }
        //遍历有向图
        for(int i=0;i<26;i++){
            for(int j=i+1;j<26;j++){
                if(graph[i][j]&&graph[j][i]){
                    return "";
                }else if(graph[i][j]){
                    //i->j
                    // if(indegree[j]==-1){
                    //     indegree[j]=1;
                    // }else{
                    indegree[j]++;
                    // }
                    // if(indegree[i]==-1){
                    //     indegree[i]=0;
                    // }
                    outnodes[i].emplace_back(j);
                }else if(graph[j][i]){
                    //j->i
                    // if(indegree[i]==-1){
                    //     indegree[i]=1;
                    // }else{
                    indegree[i]++;
                    // }
                    // if(indegree[j]==-1){
                    //     indegree[j]=0;
                    // }
                    outnodes[j].emplace_back(i);
                }
            }
        }
        queue<int>q;
        for(int i=0;i<26;i++){
            if(indegree[i]==0){
                q.push(i);
            }
        }
        string ans="";
        while(!q.empty()){
            int size=q.size();
            for(int i=0;i<size;i++){
                int u=q.front();
                q.pop();
                ans+=('a'+u);
                for(auto v:outnodes[u]){
                    indegree[v]--;
                    if(indegree[v]==0){
                        q.push(v);
                    }
                    if(indegree[v]<0){
                        // printf("???");
                        return "";
                    }
                }
            }
        }
        if(ans.length()!=cnt){
            return "";
        }
        return ans;
    }
};

标签:专项,顺序,offer,int,indegree,字母,DFS,vector,排序
From: https://www.cnblogs.com/SaltyCheese/p/17300583.html

相关文章

  • Leetcode(剑指offer专项训练)——DP专项(8)
    最长递增路径题目给定一个 mxn整数矩阵 matrix,找出其中最长递增路径的长度。对于每个单元格,你可以往上,下,左,右四个方向移动。不能在对角线方向上移动或移动到边界外(即不允许环绕)。链接DP但是依旧不能覆盖所有的情况classSolution{public:intlongest......
  • 剑指offer05(Java)-替换空格(简单)
    题目:请实现一个函数,把字符串s中的每个空格替换成"%20"。 示例1:输入:s="Wearehappy."输出:"We%20are%20happy." 限制:0<=s的长度<=10000来源:力扣(LeetCode)链接:https://leetcode.cn/problems/ti-huan-kong-ge-lcof著作权归领扣网络所有。商业转载请联系官方授权,......
  • 剑指 Offer 40. 最小的k个数
    题目链接:剑指Offer40.最小的k个数方法:排序解题思路基于比较的排序,最低时间复杂度为\(O(nlogn)\),空间复杂度为\(O(1)\);哈希计数,时间复杂度为\(O(n)\),但需要额外的空间。代码//基于比较的排序classSolution{public:vector<int>getLeastNumbers(vector<int>&a......
  • 剑指 Offer 36. 二叉搜索树与双向链表
    题目链接:剑指Offer36.二叉搜索树与双向链表方法一:回溯解题思路代码classSolution{private:intmx=INT_MIN,mi=INT_MAX;Node*start=NULL,*end=NULL;public:voidLrotate(Node*root,Node*last_root){//针对左子树,左旋if(!ro......
  • 剑指 Offer 37. 序列化二叉树
    题目链接:剑指Offer37.序列化二叉树取巧做法classCodec{private:TreeNode*root;public://Encodesatreetoasinglestring.stringserialize(TreeNode*root){this->root=root;return"";}//Decodesyourencoded......
  • 剑指 Offer 33. 二叉搜索树的后序遍历序列
    题目链接:剑指Offer33.二叉搜索树的后序遍历序列方法:分治解题思路首先假设该序列能够构成某个二叉搜索树的后序遍历序列,那么这个序列会被分成3个部分:左子树序列,右子树序列,父节点,其中左右子树节点数可能为0;现在就可以检查该序列是否符合这个规律,然后递归的判断子树是否符合......
  • 剑指 Offer 20. 表示数值的字符串
    题目链接:剑指Offer20.表示数值的字符串方法:模拟解题思路根据题意模拟,详情见代码注释。代码classSolution{public:boolisDecimal(strings){intfirst_symbol=s.find_first_of('.');//第一个'.'的位置intlast_symbol=s.find_last_of('.'......
  • 剑指 Offer 19. 正则表达式匹配
    题目链接:剑指Offer19.正则表达式匹配方法:动态规划解题思路详情见:逐行详细讲解,由浅入深,dp和递归两种思路代码classSolution{public:boolisMatch(strings,stringp){intn=s.size(),m=p.size();boolf[n+1][m+1];//f[i][j]代表s......
  • HJ67_24点游戏算法_多维递归_DFS(深度优先搜索)
    思路:多维递归,深度有限遍历加减乘除四种情况。知识点:1、多维递归不能对传递的变量进行修改,否则无法回溯。应该传递一个新地址的变量,如代码所示,传递切片的列表,不修改列表  2、搜索遗漏。两括号比如((9-4)-1)*6选取任意一个数作为第一个运算数与24运算,不能找出所有24点的计算......
  • Leetcode(剑指offer专项训练)——DFS/BFS专项(1)
    计算除法题目给定一个变量对数组equations和一个实数值数组values作为已知条件,其中equations[i]=[Ai,Bi]和values[i]共同表示等式Ai/Bi=values[i]。每个Ai或Bi是一个表示单个变量的字符串。另有一些以数组queries表示的问题,其中queries[j]=[Cj,Dj]......