LEETCODE拾萃(算法篇)——暴力破解(DFS剥险、BFS聪蘸、PERMUTATION)

引言

現(xiàn)在互聯(lián)網(wǎng)的招工流程,算法題是必不可少的,對于像我這種沒搞過ACM的吃瓜群眾宇姚,好在有l(wèi)eetcode匈庭,拯救我于水火。于是乎浑劳,斷斷續(xù)續(xù)阱持,刷了一些題,其中一些題還是值得細(xì)細(xì)品味的魔熏,現(xiàn)把一些問題整理一下衷咽,有些解法是我自己寫的,也有些解法是參考了discuss中的答案蒜绽,當(dāng)做是秋招的一個(gè)小小總結(jié)镶骗。由于水平有限,代碼寫得并不好躲雅,選的題目也只能用于入門鼎姊,希望大家見諒。

暴力破解

暴力破解相赁,據(jù)我個(gè)人理解相寇,就是遍歷整棵搜索樹,沒有刪繁就簡钮科,緊是單單的搜索和匹配唤衫。

1、基本暴力破解:對于最基本的暴力破解绵脯,就是取出所有的可能佳励,和題目中的條件相比較,直到找到符合題意的答案蛆挫。

舉例:雞兔同籠問題赃承,已知x個(gè)頭,y只腳璃吧,問兔和雞的個(gè)數(shù)楣导。

解法:從0~x個(gè)枚舉雞(或兔)的只數(shù),計(jì)算腳的個(gè)數(shù)是否為y畜挨。

2筒繁、DFS:深度優(yōu)先搜索。從原始狀態(tài)出發(fā)巴元,選擇任一狀態(tài)毡咏,沿這個(gè)狀態(tài)一直走到?jīng)]有下一個(gè)狀態(tài)為止,這時(shí)候進(jìn)行回溯逮刨,到當(dāng)前狀態(tài)的上一個(gè)狀態(tài)呕缭,選擇另一個(gè)狀態(tài)進(jìn)行遍歷堵泽。DFS在代碼實(shí)現(xiàn)上常使用遞歸方法來實(shí)現(xiàn)。

舉例1:Leetcode 129. Sum Root to Leaf Numbers

Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number.

An example is the root-to-leaf path 1->2->3 which represents the number 123.

Find the total sum of all root-to-leaf numbers.

For example,

1
/ \
2 3

The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.

Return the sum = 12 + 13 = 25.

解法:最直觀的思路恢总,就是找到所有路徑迎罗,記錄路徑上所有的值,并且求和片仿,代碼如下:

class Solution {
public:
    int ret = 0;
    int sumNumbers(TreeNode* root) {
        if(root == nullptr) return ret;
        getSum(root,root->val);
        return ret;
    }
    //遞歸調(diào)用
    void getSum(TreeNode* root,int preval){
        if(root->left==nullptr&&root->right==nullptr){
            ret+=preval;
            return;
        }
        if(root->left)getSum(root->left,preval*10+root->left->val);
        if(root->right)getSum(root->right,preval*10+root->right->val);
        return;
    }
};

除此之外纹安,DFS還可常用于尋找所有可達(dá)狀態(tài):

舉例二:Leetcode200. Number of Islands

Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.

Example 1:

11110
11010
11000
00000

Answer: 1

Example 2:

11000
11000
00100
00011

Answer: 3

思路:在這個(gè)題目中,認(rèn)為所有為1(上下左右)組成的是一個(gè)島砂豌,求給出數(shù)組中島的個(gè)數(shù)厢岂。主要的思想就是從任一個(gè)為值1的點(diǎn)開始,將所有能達(dá)到的點(diǎn)都標(biāo)記為已訪問阳距,如果所有可達(dá)的點(diǎn)都為已訪問或0塔粒,說明這個(gè)島中所有的數(shù)據(jù)已經(jīng)被搜索完畢,則可以去找下一個(gè)島筐摘。最后可以得到島的個(gè)數(shù)卒茬。在下面的代碼中,已訪問的點(diǎn)標(biāo)記為0,如果相鄰的點(diǎn)的值為1蓄拣,說明可擴(kuò)展扬虚,則進(jìn)行擴(kuò)展。

解法:

class Solution {
public:
    int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
    int m,n,ret = 0;
    int numIslands(vector<vector<char>>& grid) {
        if(grid.empty())return 0;
        m = grid.size(),n = grid[0].size();
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(grid[i][j]=='1'){
                    dfs(i,j,grid);
                    ++ret;
                }
            }
        }
        return ret;
    }
    
    void dfs(int s,int t,vector<vector<char>>& grid) {
     //如果已經(jīng)訪問過或超界球恤,則不需要再擴(kuò)展
        if(s<0||s>=m||t<0||t>=n||grid[s][t]=='0'){
            return;
        }
     //標(biāo)記為已經(jīng)訪問過
        grid[s][t]='0';
     //向下一個(gè)狀態(tài)擴(kuò)展,進(jìn)行遞歸訪問
        for(int i=0;i<4;i++){
            dfs(s+dir[i][0],t+dir[i][1],grid);
        }
        return;
    }
};

3.BFS:廣度優(yōu)先搜索荸镊,是和DFS相對的一種方法咽斧,從初始狀態(tài)開始,用“輻射狀”的形式遍歷其余所有狀態(tài)躬存。對于狀態(tài)的遍歷张惹,BFS和DFS能使用的場景有很多有很多相似之處,例如上面的Leetcode129岭洲,就也有BFS解法宛逗。

BFS一般使用隊(duì)列實(shí)現(xiàn):將初始狀態(tài)放到隊(duì)列中,當(dāng)出隊(duì)的時(shí)候盾剩,將出隊(duì)狀態(tài)的所有未訪問過的后續(xù)狀態(tài)放到隊(duì)列中進(jìn)行后續(xù)訪問雷激。BFS的一個(gè)典型應(yīng)用是用于(最短)路徑的尋找,從初始狀態(tài)到目標(biāo)狀態(tài)告私,因?yàn)锽FS可以保證每次遍歷的時(shí)候從初始狀態(tài)到當(dāng)前隊(duì)列中的狀態(tài)的步數(shù)是相同的屎暇;另一個(gè)典型應(yīng)用是對于某種“分層”的場合,對于某一狀態(tài)驻粟,其后續(xù)的所有狀態(tài)具有相同的性質(zhì)根悼。

舉例1:LeetCode 490,但這個(gè)題是付費(fèi)的,我只看過解法挤巡,并沒有做過剩彬,迷宮類的題是BFS最經(jīng)典的應(yīng)用。題目和解法可以參考我一直比較崇拜的一個(gè)博主的博客:https://www.cnblogs.com/grandyang/p/6381458.html

** 舉例2:LeetCode 542. 01 Matrix**

Given a matrix consists of 0 and 1, find the distance of the nearest 0 for each cell.

The distance between two adjacent cells is 1.

Example 1:
Input:
0 0 0
0 1 0
0 0 0

Output:
0 0 0
0 1 0
0 0 0

Example 2:
Input:
0 0 0
0 1 0
1 1 1

Output:
0 0 0
0 1 0
1 2 1

Note:

  1. The number of elements of the given matrix will not exceed 10,000.
  2. There are at least one 0 in the given matrix.
  3. The cells are adjacent in only four directions: up, down, left and right.

解法:此題即是“分層”場景的一個(gè)典型應(yīng)用”矿卑、對于每一個(gè)0襟衰,其周圍的非0點(diǎn)的狀態(tài)相同:周圍最近的0距離為1;再以這些1為中心粪摘,擴(kuò)散出去的第二層具有相同的性質(zhì)瀑晒。

class Solution {
public:
    int dir[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
    #define pii pair<int,int>
    #define mp make_pair
    vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
        int m = matrix.size();
        if(m==0)return matrix;
        int n = matrix[0].size();
        queue<pii> q;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(matrix[i][j]==0){
                    q.push(mp(i,j));
                }else{
                    matrix[i][j]=INT_MAX;
                }
            }
        }
        while(!q.empty()){
            pii tmp = q.front();
            q.pop();
            for(int k=0;k<4;k++){
                int a = tmp.first+dir[k][0],b = tmp.second+dir[k][1];
                if(a<0||a>=m||b<0||b>=n)continue;
                if(matrix[a][b]<=matrix[tmp.first][tmp.second]) continue;
                matrix[a][b]=min(matrix[a][b],matrix[tmp.first][tmp.second]+1);
                q.push({a,b});
            }
        }
        return matrix;
    }
};

舉例3:102. Binary Tree Level Order Traversal

BFS另一個(gè)典型應(yīng)用就是用于樹或圖的層次遍歷,這個(gè)比較基本徘意,此處不再贅述苔悦。

4、Permutation:即全排列椎咧,可以獲取1~n的全排列

在C++中玖详,可以使用STL里面的接口來實(shí)現(xiàn),例如求一個(gè)數(shù)組的全排列:

class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        vector<vector<int>> ret;
        ret.push_back(nums);
        while(next_permutation(nums.begin(),nums.end())){
            ret.push_back(nums);
        }
        return ret;
    }
};

這個(gè)函數(shù)在使用之前要注意勤讽,需要將數(shù)組排序蟋座,這樣才能檢測出來當(dāng)前的排列是否生成過。

除此之外脚牍,permutation也可以用來求子集(m中選k個(gè))向臀,即使用m的全排列的前k個(gè)。

permutation的復(fù)雜度為O(n!)诸狭,一般只有數(shù)據(jù)量較小的時(shí)候可以使用券膀。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市驯遇,隨后出現(xiàn)的幾起案子芹彬,更是在濱河造成了極大的恐慌,老刑警劉巖叉庐,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舒帮,死亡現(xiàn)場離奇詭異,居然都是意外死亡陡叠,警方通過查閱死者的電腦和手機(jī)玩郊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來匾竿,“玉大人瓦宜,你說我怎么就攤上這事×胙” “怎么了临庇?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵反璃,是天一觀的道長。 經(jīng)常有香客問我假夺,道長淮蜈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任已卷,我火速辦了婚禮梧田,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘侧蘸。我一直安慰自己裁眯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布讳癌。 她就那樣靜靜地躺著穿稳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪晌坤。 梳的紋絲不亂的頭發(fā)上逢艘,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機(jī)與錄音骤菠,去河邊找鬼它改。 笑死,一個(gè)胖子當(dāng)著我的面吹牛商乎,可吹牛的內(nèi)容都是我干的央拖。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼截亦,長吁一口氣:“原來是場噩夢啊……” “哼爬泥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起崩瓤,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎踩官,沒想到半個(gè)月后却桶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蔗牡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年颖系,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辩越。...
    茶點(diǎn)故事閱讀 40,503評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嘁扼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出黔攒,到底是詐尸還是另有隱情趁啸,我是刑警寧澤强缘,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站不傅,受9級(jí)特大地震影響旅掂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜访娶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一商虐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧崖疤,春花似錦秘车、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至沦偎,卻和暖如春疫向,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背豪嚎。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工搔驼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人侈询。 一個(gè)月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓舌涨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親扔字。 傳聞我的和親對象是個(gè)殘疾皇子囊嘉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容