国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

算法沉淀——BFS 解決拓?fù)渑判颍╨eetcode真題剖析)

這篇具有很好參考價(jià)值的文章主要介紹了算法沉淀——BFS 解決拓?fù)渑判颍╨eetcode真題剖析)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

算法沉淀——BFS 解決拓?fù)渑判颍╨eetcode真題剖析),算法沉淀,算法,寬度優(yōu)先,leetcode


Breadth-First Search (BFS) 在拓?fù)渑判蛑械膽?yīng)用主要是用來解決有向無環(huán)圖(DAG)的拓?fù)渑判騿栴}。拓?fù)渑判蚴菍?duì)有向圖中所有節(jié)點(diǎn)的一種線性排序,使得對(duì)于每一條有向邊 (u, v),節(jié)點(diǎn) u 在排序中都出現(xiàn)在節(jié)點(diǎn) v 的前面。如果圖中存在環(huán)路,則無法進(jìn)行拓?fù)渑判颉?

BFS 解決拓?fù)渑判虻牟襟E如下:

  1. 統(tǒng)計(jì)每個(gè)節(jié)點(diǎn)的入度(in-degree),即指向該節(jié)點(diǎn)的邊的數(shù)量。
  2. 將所有入度為 0 的節(jié)點(diǎn)加入隊(duì)列。
  3. 對(duì)于每個(gè)入度為 0 的節(jié)點(diǎn),依次出隊(duì),更新其相鄰節(jié)點(diǎn)的入度,將入度變?yōu)?0 的節(jié)點(diǎn)加入隊(duì)列。
  4. 重復(fù)步驟 3 直到隊(duì)列為空。

如果最終遍歷過的節(jié)點(diǎn)數(shù)等于圖中的節(jié)點(diǎn)數(shù),說明圖是有向無環(huán)圖,可以得到一個(gè)拓?fù)渑判颉?/p>

01.課程表

題目鏈接:https://leetcode.cn/problems/course-schedule/

你這個(gè)學(xué)期必須選修 numCourses 門課程,記為 0numCourses - 1 。

在選修某些課程之前需要一些先修課程。 先修課程按數(shù)組 prerequisites 給出,其中 prerequisites[i] = [ai, bi] ,表示如果要學(xué)習(xí)課程 ai必須 先學(xué)習(xí)課程 bi 。

  • 例如,先修課程對(duì) [0, 1] 表示:想要學(xué)習(xí)課程 0 ,你需要先完成課程 1 。

請(qǐng)你判斷是否可能完成所有課程的學(xué)習(xí)?如果可以,返回 true ;否則,返回 false 。

示例 1:

輸入:numCourses = 2, prerequisites = [[1,0]]
輸出:true
解釋:總共有 2 門課程。學(xué)習(xí)課程 1 之前,你需要完成課程 0 。這是可能的。

示例 2:

輸入:numCourses = 2, prerequisites = [[1,0],[0,1]]
輸出:false
解釋:總共有 2 門課程。學(xué)習(xí)課程 1 之前,你需要先完成課程 0 ;并且學(xué)習(xí)課程 0 之前,你還應(yīng)先完成課程 1 。這是不可能的。

提示:

  • 1 <= numCourses <= 2000
  • 0 <= prerequisites.length <= 5000
  • prerequisites[i].length == 2
  • 0 <= ai, bi < numCourses
  • prerequisites[i] 中的所有課程對(duì) 互不相同

思路

這里我們可以采用容器模擬鄰接矩陣或者鄰接表來進(jìn)行拓?fù)渑判颍袛噙@個(gè)圖是否有環(huán)的方式來解決這個(gè)問題

代碼文章來源地址http://www.zghlxwxcb.cn/news/detail-834379.html

class Solution {
public:
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        unordered_map<int,vector<int>> edges;
        vector<int> in(numCourses,0);

        for(vector<int>& e:prerequisites){
            int a=e[0],b=e[1];
            edges[b].push_back(a);
            in[a]++;
        }

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

        while(!q.empty()){
            int t=q.front();
            q.pop();
            for(int e:edges[t]){
                in[e]--;
                if(in[e]==0) q.push(e);
            }
        }

        for(int i:in) if(i) return false;
        return true;
    }
};
  1. 使用一個(gè)哈希表 edges 存儲(chǔ)有向圖的邊,其中 edges[b] 表示節(jié)點(diǎn) b 指向的所有節(jié)點(diǎn)。
  2. 使用數(shù)組 in 記錄每個(gè)節(jié)點(diǎn)的入度。初始化時(shí),將所有節(jié)點(diǎn)的入度設(shè)為 0。
  3. 遍歷先修課程的關(guān)系,構(gòu)建有向圖并更新入度數(shù)組。
  4. 將入度為 0 的節(jié)點(diǎn)加入隊(duì)列 q。
  5. 使用 BFS 進(jìn)行拓?fù)渑判颍瑥娜攵葹?0 的節(jié)點(diǎn)開始,依次出隊(duì),并將其鄰接節(jié)點(diǎn)的入度減 1。如果鄰接節(jié)點(diǎn)的入度減為 0,將其加入隊(duì)列。
  6. 如果最終所有節(jié)點(diǎn)的入度都為 0,說明圖中不存在環(huán),可以完成所有課程,返回 true;否則,返回 false。

02.課程表 II

題目鏈接:https://leetcode.cn/problems/course-schedule-ii/

現(xiàn)在你總共有 numCourses 門課需要選,記為 0numCourses - 1。給你一個(gè)數(shù)組 prerequisites ,其中 prerequisites[i] = [ai, bi] ,表示在選修課程 ai必須 先選修 bi 。

  • 例如,想要學(xué)習(xí)課程 0 ,你需要先完成課程 1 ,我們用一個(gè)匹配來表示:[0,1] 。

返回你為了學(xué)完所有課程所安排的學(xué)習(xí)順序??赡軙?huì)有多個(gè)正確的順序,你只要返回 任意一種 就可以了。如果不可能完成所有課程,返回 一個(gè)空數(shù)組

示例 1:

輸入:numCourses = 2, prerequisites = [[1,0]]
輸出:[0,1]
解釋:總共有 2 門課程。要學(xué)習(xí)課程 1,你需要先完成課程 0。因此,正確的課程順序?yàn)?[0,1] 。

示例 2:

輸入:numCourses = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]]
輸出:[0,2,1,3]
解釋:總共有 4 門課程。要學(xué)習(xí)課程 3,你應(yīng)該先完成課程 1 和課程 2。并且課程 1 和課程 2 都應(yīng)該排在課程 0 之后。
因此,一個(gè)正確的課程順序是 [0,1,2,3] 。另一個(gè)正確的排序是 [0,2,1,3] 。

示例 3:

輸入:numCourses = 1, prerequisites = []
輸出:[0]

思路

總體思路和上面一致,我們只需要在每次將入度為0的點(diǎn)順序保存即為拓?fù)渑判虻捻樞颉?/p>

代碼

class Solution {
public:
    vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
        unordered_map<int,vector<int>> edges;
        vector<int> in(numCourses,0);

        for(vector<int>& e:prerequisites){
            int a=e[0],b=e[1];
            edges[b].push_back(a);
            in[a]++;
        }

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

        while(!q.empty()){
            int t=q.front();
            q.pop();
            for(int e:edges[t]){
                in[e]--;
                if(in[e]==0){ 
                    q.push(e);
                    ret.push_back(e);    
                }
            }
        }

        for(int i:in) if(i) return {};
        return ret;
    }
};
  1. 使用一個(gè)哈希表 edges 存儲(chǔ)有向圖的邊,其中 edges[b] 表示節(jié)點(diǎn) b 指向的所有節(jié)點(diǎn)。
  2. 使用數(shù)組 in 記錄每個(gè)節(jié)點(diǎn)的入度。初始化時(shí),將所有節(jié)點(diǎn)的入度設(shè)為 0。
  3. 遍歷先修課程的關(guān)系,構(gòu)建有向圖并更新入度數(shù)組。
  4. 將入度為 0 的節(jié)點(diǎn)加入隊(duì)列 q,同時(shí)將這些節(jié)點(diǎn)加入結(jié)果數(shù)組 ret 中。
  5. 使用 BFS 進(jìn)行拓?fù)渑判颍瑥娜攵葹?0 的節(jié)點(diǎn)開始,依次出隊(duì),并將其鄰接節(jié)點(diǎn)的入度減 1。如果鄰接節(jié)點(diǎn)的入度減為 0,將其加入隊(duì)列和結(jié)果數(shù)組。
  6. 如果最終所有節(jié)點(diǎn)的入度都為 0,說明圖中不存在環(huán),返回拓?fù)渑判蚪Y(jié)果;否則,返回空數(shù)組表示無法完成拓?fù)渑判?/li>

03.火星詞典

題目鏈接:https://leetcode.cn/problems/Jf1JuT

現(xiàn)有一種使用英語字母的外星文語言,這門語言的字母順序與英語順序不同。

給定一個(gè)字符串列表 words ,作為這門語言的詞典,words 中的字符串已經(jīng) 按這門新語言的字母順序進(jìn)行了排序 。

請(qǐng)你根據(jù)該詞典還原出此語言中已知的字母順序,并 按字母遞增順序 排列。若不存在合法字母順序,返回 "" 。若存在多種可能的合法字母順序,返回其中 任意一種 順序即可。

字符串 s 字典順序小于 字符串 t 有兩種情況:

  • 在第一個(gè)不同字母處,如果 s 中的字母在這門外星語言的字母順序中位于 t 中字母之前,那么 s 的字典順序小于 t 。
  • 如果前面 min(s.length, t.length) 字母都相同,那么 s.length < t.length 時(shí),s 的字典順序也小于 t

示例 1:

輸入:words = ["wrt","wrf","er","ett","rftt"]
輸出:"wertf"

示例 2:

輸入:words = ["z","x"]
輸出:"zx"

示例 3:

輸入:words = ["z","x","z"]
輸出:""
解釋:不存在合法字母順序,因此返回 "" 。

提示:

  • 1 <= words.length <= 100
  • 1 <= words[i].length <= 100
  • words[i] 僅由小寫英文字母組成

思路

將題意搞清楚之后,這道題就變成了判斷有向圖時(shí)候有環(huán),可以用拓?fù)渑判蚪鉀Q。
如何搜集信息(如何建圖):
a. 兩層for循環(huán)枚舉出所有的兩個(gè)字符串的組合;
b. 然后利用指針,根據(jù)字典序規(guī)則找出信息。

  1. 使用哈希表 edges 存儲(chǔ)字母之間的順序關(guān)系,其中 edges[a] 表示字母 a 后面可以跟隨的字母集合。
  2. 使用哈希表 in 記錄每個(gè)字母的入度,即有多少字母在它之前。
  3. 使用布爾變量 cheak 標(biāo)記是否出現(xiàn)了無效的字母順序。
  4. 定義 add 函數(shù),該函數(shù)比較兩個(gè)單詞 s1s2,找到它們第一個(gè)不相同的字母,然后將這個(gè)字母的順序關(guān)系添加到 edges 中。如果 s2s1 的前綴,則將 cheak 設(shè)置為 true。
  5. 在構(gòu)建字母之間的順序關(guān)系時(shí),遍歷相鄰的兩個(gè)單詞,調(diào)用 add 函數(shù),如果 cheaktrue,則直接返回空字符串。
  6. 使用隊(duì)列 q 存儲(chǔ)入度為 0 的字母,初始化隊(duì)列時(shí)將所有入度為 0 的字母加入。
  7. 使用 BFS 進(jìn)行拓?fù)渑判颍粩鄬⑷攵葹?0 的字母出隊(duì),并將其后面可以跟隨的字母的入度減 1。將入度為 0 的字母加入結(jié)果字符串 ret 中。
  8. 最后檢查所有字母的入度是否都為 0,如果不為 0,則說明有環(huán),返回空字符串;否則,返回結(jié)果字符串 ret。

代碼

class Solution {
    unordered_map<char,unordered_set<char>> edges;
    unordered_map<char,int> in;
    bool cheak=false;

    void add(string& s1,string& s2){
        int n=min(s1.size(),s2.size());
        int i=0;

        while(i<n){
            if(s1[i]!=s2[i]){
                char a=s1[i],b=s2[i];
                if(!edges.count(a)||!edges[a].count(b)){
                    edges[a].insert(b);
                    in[b]++;
                }
                break;
            }
            i++;
        }
        if(i==s2.size()&&i<s1.size()) cheak=true;
    }
public:
    string alienOrder(vector<string>& words) {
        for(auto& s:words)
            for(auto& ch:s)
                in[ch]=0;

        int n=words.size();
        for(int i=0;i<n;i++)
            for(int j=i+1;j<n;j++){
                add(words[i],words[j]);
                if(cheak) return "";
            }
        
        queue<char> q;
        for(auto& [a,b]:in)
            if(b==0) q.push(a);
        
        string ret;
        while(!q.empty()){
            char t=q.front();
            q.pop();
            ret+=t;
            for(char ch:edges[t])
                if(--in[ch]==0) q.push(ch);
        }

        for(auto& [a,b]:in) if(b) return "";

        return ret;
    }
};

到了這里,關(guān)于算法沉淀——BFS 解決拓?fù)渑判颍╨eetcode真題剖析)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包