日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

c语言中dfs用pos做参数,LeetCode算法练习——深度优先搜索 DFS(2)

發(fā)布時(shí)間:2023/12/3 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c语言中dfs用pos做参数,LeetCode算法练习——深度优先搜索 DFS(2) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

更多干貨就在我的個(gè)人博客 BlackBlog.tech 歡迎關(guān)注!

也可以關(guān)注我的csdn博客:黑哥的博客

謝謝大家!

我們繼續(xù)LeetCode之旅.

做了一段時(shí)間的LeetCode,感覺(jué)還是不錯(cuò)的。算法很基礎(chǔ),沒(méi)有特別難的(至少我看在做的),很適合考試,面試,就業(yè)之前的訓(xùn)練。對(duì)提升基本功很有幫助,我覺(jué)得如果有時(shí)間的話,每天都做上幾道,日積月累,代碼能力必然有提高。

這一篇繼續(xù)進(jìn)行DFS的練習(xí),預(yù)計(jì)還會(huì)有十道題。

給個(gè)目錄:

LeetCode109 有序鏈表轉(zhuǎn)換二叉搜索樹(shù)

LeetCode332 重新安排行程

LeetCode337 打家劫舍 III

LeetCode394 字符串解碼

LeetCode417 太平洋大西洋水流問(wèn)題

LeetCode473 火柴拼正方形

LeetCode494 目標(biāo)和

LeetCode491 遞增子序列

LeetCode515 在每個(gè)樹(shù)行中找最大值

LeetCode513 找樹(shù)左下角的值

LeetCode109 有序鏈表轉(zhuǎn)換二叉搜索樹(shù)

題目

給定一個(gè)單鏈表,其中的元素按升序排序,將其轉(zhuǎn)換為高度平衡的二叉搜索樹(shù)。

本題中,一個(gè)高度平衡二叉樹(shù)是指一個(gè)二叉樹(shù)每個(gè)節(jié)點(diǎn) 的左右兩個(gè)子樹(shù)的高度差的絕對(duì)值不超過(guò) 1。

示例:

給定的有序鏈表: [-10, -3, 0, 5, 9],

一個(gè)可能的答案是:[0, -3, 9, -10, null, 5], 它可以表示下面這個(gè)高度平衡二叉搜索樹(shù):

0

/ \

-3 9

/ /

-10 5

C++代碼

class Solution {

public:

bool isValidBST(TreeNode* root) {

return dfs(root,LONG_MAX,LONG_MIN);

}

bool dfs(TreeNode* root, long max,long min){

if(!root) return true;

if(root->val<=min || root->val>=max) return false;

else return (dfs(root->left,root->val,min) && dfs(root->right,max,root->val));

}

};

體會(huì)

這個(gè)題利用了二叉檢索樹(shù)自身的性質(zhì),左邊節(jié)點(diǎn)小于根節(jié)點(diǎn),右邊節(jié)點(diǎn)大于根節(jié)點(diǎn)。初始化時(shí)帶入系統(tǒng)最大值和最小值,在遞歸過(guò)程中換成它們自己的節(jié)點(diǎn)值,用long代替int就是為了包括int的邊界條件。

如果這棵樹(shù)遍歷到了葉節(jié)點(diǎn),則返回true。如果在遍歷的過(guò)程中出現(xiàn)了當(dāng)前節(jié)點(diǎn)大于等于父節(jié)點(diǎn)(左子樹(shù))或小于等于父節(jié)點(diǎn)(右子樹(shù))則返回false。對(duì)結(jié)果做&&運(yùn)算。返回最終的結(jié)果。

LeetCode332 重新安排行程

題目

給定一個(gè)機(jī)票的字符串二維數(shù)組 [from, to],子數(shù)組中的兩個(gè)成員分別表示飛機(jī)出發(fā)和降落的機(jī)場(chǎng)地點(diǎn),對(duì)該行程進(jìn)行重新規(guī)劃排序。所有這些機(jī)票都屬于一個(gè)從JFK(肯尼迪國(guó)際機(jī)場(chǎng))出發(fā)的先生,所以該行程必須從 JFK 出發(fā)。

說(shuō)明:

如果存在多種有效的行程,你可以按字符自然排序返回最小的行程組合。例如,行程 ["JFK", "LGA"] 與 ["JFK", "LGB"] 相比就更小,排序更靠前

所有的機(jī)場(chǎng)都用三個(gè)大寫(xiě)字母表示(機(jī)場(chǎng)代碼)。

假定所有機(jī)票至少存在一種合理的行程

示例 1:

tickets = [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]]

返回["JFK", "MUC", "LHR", "SFO", "SJC"]

示例 2:

tickets = [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]

返回["JFK","ATL","JFK","SFO","ATL","SFO"]

另一種有效的行程是 ["JFK","SFO","ATL","JFK","ATL","SFO"]。但是它自然排序更大更靠后。

C++代碼

class Solution {

public:

unordered_map> hash; //用來(lái)存儲(chǔ)起點(diǎn)與終點(diǎn)的信息

vector res; //最終的路徑結(jié)果

vector findItinerary(vector> tickets) {

if(tickets.size()==0) return {}; //如果輸入為空 返回空

for (int i=0;i

hash[tickets[i].first].insert(tickets[i].second); //將ticket轉(zhuǎn)化為hash

}

dfs("JFK"); //dfs

reverse(res.begin(), res.end()); //因?yàn)樽罱K得到的結(jié)果是一個(gè)反序列的 我們要返回來(lái)

return res;

}

void dfs(string from){

while(hash[from].size()>0){ //如果當(dāng)前起點(diǎn)還有終點(diǎn)沒(méi)有去過(guò)的話

string tem = *hash[from].begin(); //記錄下當(dāng)前起點(diǎn)去往的第一個(gè)終點(diǎn)

hash[from].erase(hash[from].begin()); //將第一個(gè)終點(diǎn)從hash中刪除

dfs(tem); //繼續(xù)dfs

}

res.push_back(from); //將當(dāng)前的出發(fā)點(diǎn)加入res

}

};

體會(huì)

題目看起來(lái)并沒(méi)有什么難度。DFS+回溯,但我覺(jué)得有坑。。。

第一次寫(xiě),寫(xiě)的這個(gè)代碼,所有樣例測(cè)試完全正確。

class Solution {

private:

vector res;

public:

vector findItinerary(vector> tickets) {

vector path;

vector mark;

for(int i=0;i

mark.push_back(0);

path.push_back("JFK");

dfs(tickets,mark,path,"JFK");

tickets.clear();

path.clear();

mark.clear();

return res;

}

void dfs(vector> tickets, vector mark, vector path, string from){

int flag = true;

for(int i=0;i

if(mark[i]==0) flag=false;

}

if(flag == true){

res = path;

return;

}

for(int i=0;i

if(tickets[i].first==from && mark[i]==0){

path.push_back(tickets[i].second);

mark[i] = 1;

dfs(tickets,mark,path,tickets[i].second);

mark[i]=0;

path.pop_back();

}

}

return;

}

};

可是,每次提交都會(huì)報(bào)一個(gè)錯(cuò)誤,本地調(diào)試也沒(méi)有問(wèn)題。就很迷。

換了思路重新寫(xiě)。

各位有興趣麻煩幫我檢查一下代碼。

另外,此題少給出了一個(gè)條件。就是默認(rèn)輸出最長(zhǎng)的路徑,路徑長(zhǎng)度相同時(shí),再以字典序列輸出。

LeetCode337 打家劫舍 III

題目

小偷又發(fā)現(xiàn)一個(gè)新的可行竊的地點(diǎn)。 這個(gè)地區(qū)只有一個(gè)入口,稱為“根”。 除了根部之外,每棟房子有且只有一個(gè)父房子。 一番偵察之后,聰明的小偷意識(shí)到“這個(gè)地方的所有房屋形成了一棵二叉樹(shù)”。 如果兩個(gè)直接相連的房子在同一天晚上被打劫,房屋將自動(dòng)報(bào)警。

在不觸動(dòng)警報(bào)的情況下,計(jì)算小偷一晚能盜取的最高金額。

示例 1:

3

/ \

2 3

\ \

3 1

能盜取的最高金額 = 3 + 3 + 1 = 7.

示例 2:

3

/ \

4 5

/ \ \

1 3 1

能盜取的最高金額 = 4 + 5 = 9.

C++代碼

class Solution {

public:

//偷 對(duì)第一個(gè)根節(jié)點(diǎn) 采取偷與不偷的方式 最后求最大值

int rob(TreeNode* root) {

if(!root) return 0;

return std::max(robRoot(root),notRobRoot(root));

}

//偷根節(jié)點(diǎn)的情況 就不能偷兩個(gè)子節(jié)點(diǎn)

int robRoot(TreeNode *root){

if(!root) return 0;

return notRobRoot(root->left) +notRobRoot(root->right)+root->val;

}

//不偷根節(jié)點(diǎn)的情況 可以偷兩個(gè)子節(jié)點(diǎn) 但不一定就要偷

int notRobRoot(TreeNode *root){

if(!root) return 0;

return rob(root->left) + rob(root->right);

}

};

體會(huì)

這個(gè)題屬于思路很清晰就很簡(jiǎn)單的題。

首先我們來(lái)分析題目,題目中說(shuō)如果兩個(gè)節(jié)點(diǎn)連在一起,那么偷東西就會(huì)被發(fā)現(xiàn)。所有只要我們偷東西的節(jié)點(diǎn)不連在一起就沒(méi)有問(wèn)題。連在一起的情況只有根節(jié)點(diǎn)與子節(jié)點(diǎn)。

對(duì)于一個(gè)根節(jié)點(diǎn)分為偷與不偷兩種情況,如果偷的話,那么他的子節(jié)點(diǎn)就不能偷;如果不偷的話,可以偷他的子節(jié)點(diǎn),也可以不偷,根據(jù)偷到的金額去做判斷。對(duì)于每個(gè)根節(jié)點(diǎn),我們要把這兩周情況都考慮上,代碼如上。

LeetCode394 字符串解碼

題目

給定一個(gè)經(jīng)過(guò)編碼的字符串,返回它解碼后的字符串。

編碼規(guī)則為: k[encoded_string],表示其中方括號(hào)內(nèi)部的 encoded_string 正好重復(fù) k 次。注意 k 保證為正整數(shù)。

你可以認(rèn)為輸入字符串總是有效的;輸入字符串中沒(méi)有額外的空格,且輸入的方括號(hào)總是符合格式要求的。

此外,你可以認(rèn)為原始數(shù)據(jù)不包含數(shù)字,所有的數(shù)字只表示重復(fù)的次數(shù) k ,例如不會(huì)出現(xiàn)像 3a 或 2[4] 的輸入。

示例:

s = "3[a]2[bc]", 返回 "aaabcbc".

s = "3[a2[c]]", 返回 "accaccacc".

s = "2[abc]3[cd]ef", 返回 "abcabccdcdcdef".

C++代碼

class Solution {

public:

string decodeString(string s) {

dfs(s);

return s;

}

void dfs(string &s){

int l=0,r=0; //方括號(hào)的左起點(diǎn) 右起點(diǎn)

string num_s=""; //存儲(chǔ)數(shù)字的部分

int num_len =0; //數(shù)字的長(zhǎng)度

int num; //數(shù)字本身

//遍歷找方括號(hào)

for(int i=0;i

if(s[i]=='[') { //如果是左括號(hào)

l = i; //記錄位置

num = atoi(num_s.data()); //將之前存儲(chǔ)的num轉(zhuǎn)換為數(shù)字

num_len=num_s.size(); //得到數(shù)字的長(zhǎng)度 用于后面裁切字符串

num_s.clear(); //清空 方式影響后面內(nèi)容

}

else if(s[i]==']') {

r = i; //記錄右括號(hào)位置

break; //結(jié)束循環(huán)

}

else if(s[i]<='9' && s[i]>='0') num_s+=s[i]; //記錄每一位的數(shù)字

}

if(l>=r) return ; //結(jié)束條件

string newstr=""; //預(yù)備重復(fù)的部分字符串

for(int i=0;i

newstr+=s.substr(l+1,r-l-1); //重復(fù)字符串

s = s.substr(0,l-num_len)+newstr+s.substr(r+1,s.length()-r-1); //制作新的字符串

dfs(s);//遞歸調(diào)用

}

};

體會(huì)

算是一道完全的模擬題。

我用的思路比較簡(jiǎn)單,每次都只處理最里面的一個(gè)[],將其中的內(nèi)容重復(fù)。逐次遞歸調(diào)用,最后解析完所有的字符串。注意s = s.substr(0,l-num_len)+newstr+s.substr(r+1,s.length()-r-1);各個(gè)字符串的起始位置和裁切長(zhǎng)度。

LeetCode417 太平洋大西洋水流問(wèn)題

題目

給定一個(gè) m x n 的非負(fù)整數(shù)矩陣來(lái)表示一片大陸上各個(gè)單元格的高度。“太平洋”處于大陸的左邊界和上邊界,而“大西洋”處于大陸的右邊界和下邊界。

規(guī)定水流只能按照上、下、左、右四個(gè)方向流動(dòng),且只能從高到低或者在同等高度上流動(dòng)。

請(qǐng)找出那些水流既可以流動(dòng)到“太平洋”,又能流動(dòng)到“大西洋”的陸地單元的坐標(biāo)。

提示:

輸出坐標(biāo)的順序不重要

m 和 n 都小于150

示例:

給定下面的 5x5 矩陣:

太平洋 ~ ~ ~ ~ ~

~ 1 2 2 3 (5) *

~ 3 2 3 (4) (4) *

~ 2 4 (5) 3 1 *

~ (6) (7) 1 4 5 *

~ (5) 1 1 2 4 *

* * * * * 大西洋

返回:

[[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]] (上圖中帶括號(hào)的單元).

C++代碼

class Solution {

public:

vector> pacificAtlantic(vector>& matrix) {

if (matrix.empty() || matrix[0].empty()) return {};

int m = matrix.size(); //矩陣行數(shù)

int n = matrix[0].size(); //矩陣列數(shù)

vector> res; //最終結(jié)果

vector> pacific(m, vector(n, false)); //太平洋

vector> atlantic(m, vector(n, false)); //大西洋

//遍歷第一行,最底下一行

for(int i=0;i

dfs(matrix,pacific,i,0,matrix[i][0]);

dfs(matrix,atlantic,i,n-1,matrix[i][n-1]);

}

//遍歷第一列,最右邊一列

for(int i=0;i

dfs(matrix,pacific,0,i,matrix[0][i]);

dfs(matrix,atlantic,m-1,i,matrix[m-1][i]);

}

//將pacific與atlantic重合的部分 作為最終結(jié)果

for(int i=0;i

for(int j=0;j

if(atlantic[i][j] && pacific[i][j])

res.push_back(make_pair(i,j));

}

}

return res;

}

void dfs(vector>& matrix,vector> &visited,int x,int y,int val){

//越界 被訪問(wèn) 或者 當(dāng)前值小于上一個(gè)值的都直接返回

if (x<0 || x>matrix.size()-1 || y<0 || y>matrix[0].size()-1 || visited[x][y] || matrix[x][y] < val) return;

//將該坐標(biāo)設(shè)置為訪問(wèn)過(guò)

visited[x][y] = true;

dfs(matrix,visited,x+1,y,matrix[x][y]);

dfs(matrix,visited,x-1,y,matrix[x][y]);

dfs(matrix,visited,x,y+1,matrix[x][y]);

dfs(matrix,visited,x,y-1,matrix[x][y]);

}

};

體會(huì)

這個(gè)題第一眼看到覺(jué)得是一個(gè)很簡(jiǎn)單DFS搜索題。第一個(gè)想法肯定是對(duì)每一個(gè)點(diǎn)進(jìn)行dfs,看他是否能夠走到太平洋或者大西洋。顯然這樣,時(shí)間復(fù)雜度會(huì)很高。我們可以對(duì)其優(yōu)化,每一次得到一條路徑后,將路徑上的所有點(diǎn)都記錄下來(lái),這樣可以減少很多次dfs的過(guò)程,但優(yōu)化效果不明顯。

這個(gè)題,我們采用倒推法的思路。從大西洋、太平洋向內(nèi)搜索,每次找比當(dāng)前節(jié)點(diǎn)高的或者相同的節(jié)點(diǎn),將這些節(jié)點(diǎn)設(shè)置為T(mén)rue。最終將大西洋中為T(mén)rue的,太平洋中也為T(mén)rue的節(jié)點(diǎn)作為最終的答案。

LeetCode473 火柴拼正方形

題目

還記得童話《賣火柴的小女孩》嗎?現(xiàn)在,你知道小女孩有多少根火柴,請(qǐng)找出一種能使用所有火柴拼成一個(gè)正方形的方法。不能折斷火柴,可以把火柴連接起來(lái),并且每根火柴都要用到。

輸入為小女孩擁有火柴的數(shù)目,每根火柴用其長(zhǎng)度表示。輸出即為是否能用所有的火柴拼成正方形。

示例 1:

輸入: [1,1,2,2,2]

輸出: true

解釋: 能拼成一個(gè)邊長(zhǎng)為2的正方形,每邊兩根火柴。

示例 2:

輸入: [3,3,3,3,4]

輸出: false

解釋: 不能用所有火柴拼成一個(gè)正方形。

注意:

給定的火柴長(zhǎng)度和在 0 到 10^9之間。

火柴數(shù)組的長(zhǎng)度不超過(guò)15。

C++代碼

class Solution {

public:

bool makesquare(vector& nums) {

if(nums.size()<4 || nums.size()==0) return false; //如果數(shù)組的大小不滿足4 就直接返回0

int sum = accumulate(nums.begin(),nums.end(),0); //對(duì)整個(gè)數(shù)組進(jìn)行求和

int target = sum /4 ; //計(jì)算每一條邊需要的長(zhǎng)度

vector sums(4,0); //新建一個(gè)長(zhǎng)度為4的數(shù)組,用來(lái)記錄每一個(gè)邊當(dāng)前的長(zhǎng)度

sort(nums.rbegin(),nums.rend()); //對(duì)數(shù)組進(jìn)行排序,先計(jì)算大的,這樣可以優(yōu)化不少效率

bool res = dfs(nums,sums,0,target); // dfs

return res;

}

bool dfs(vector& nums,vector sums, int pos, int target){

if(pos>nums.size()-1){ //如果pos>nums.size()-1證明數(shù)組已經(jīng)被遍歷完,判斷當(dāng)前所有的邊是否都滿足要求

return sums[0]==target && sums[1]==target && sums[2]==target && sums[3]==target;

}

//對(duì)每一條邊進(jìn)行嘗試

for(int i=0;i<4;i++){

if(sums[i]+nums[pos]>target) continue; //如果i邊 放入一個(gè)數(shù)字后,超過(guò)target則不放入,進(jìn)入下一條邊

sums[i]+=nums[pos]; //i邊 長(zhǎng)度增加

if(dfs(nums,sums,pos+1,target)) return true; //pos+1 繼續(xù)dfs

sums[i]-=nums[pos]; //回溯

}

return false;

}

};

體會(huì)

這個(gè)題是一個(gè)比較標(biāo)準(zhǔn)DFS+回溯題。這問(wèn)題可以理解為,一個(gè)數(shù)組如何分為四個(gè)相同的數(shù)。我們創(chuàng)建一個(gè)數(shù)組,長(zhǎng)度為四,用來(lái)表明四條邊當(dāng)前的長(zhǎng)度,每次遍歷時(shí)將當(dāng)前的長(zhǎng)度與待放入長(zhǎng)度相加后target進(jìn)行比較。大于,則不放入,小于,則放入,不斷dfs,每次pos+1。當(dāng)pos超出范圍時(shí),證明所有的數(shù)字都被嘗試過(guò),返回當(dāng)前的狀態(tài)。

LeetCode494 目標(biāo)和

題目

給定一個(gè)非負(fù)整數(shù)數(shù)組,a1, a2, ..., an, 和一個(gè)目標(biāo)數(shù),S。現(xiàn)在你有兩個(gè)符號(hào) + 和 -。對(duì)于數(shù)組中的任意一個(gè)整數(shù),你都可以從 + 或 -中選擇一個(gè)符號(hào)添加在前面。

返回可以使最終數(shù)組和為目標(biāo)數(shù) S 的所有添加符號(hào)的方法數(shù)。

示例 1:

輸入: nums: [1, 1, 1, 1, 1], S: 3

輸出: 5

解釋:

-1+1+1+1+1 = 3

+1-1+1+1+1 = 3

+1+1-1+1+1 = 3

+1+1+1-1+1 = 3

+1+1+1+1-1 = 3

一共有5種方法讓最終目標(biāo)和為3。

注意:

數(shù)組的長(zhǎng)度不會(huì)超過(guò)20,并且數(shù)組中的值全為正數(shù)。

初始的數(shù)組的和不會(huì)超過(guò)1000。

保證返回的最終結(jié)果為32位整數(shù)。

C++代碼

class Solution {

public:

int solution =0; //方案數(shù)

int findTargetSumWays(vector& nums, int S) {

int sum = 0;

dfs(nums,S,0,sum);

return solution;

}

void dfs(vector& nums,int S,int pos,int sum){

//S表示最后結(jié)果,pos表示當(dāng)前位置,sum表示目前總和

if(pos>nums.size()-1) {

if(sum == S) solution+=1; //如果當(dāng)前sum==S 方案數(shù)+1

return ;

}

sum += nums[pos]; //先嘗試+

dfs(nums,S,pos+1,sum); //dfs

sum -= nums[pos]; //回溯

sum -= nums[pos]; //嘗試-

dfs(nums,S,pos+1,sum); //dfs

sum += nums[pos]; //回溯

return ;

}

};

體會(huì)

一道非常清晰的DFS+回溯題,我覺(jué)得都可以做標(biāo)準(zhǔn)模版了。S表示最后結(jié)果,pos表示當(dāng)前位置,sum表示目前總和,solution表示方案數(shù)。dfs中先嘗試+,回溯后,嘗試-。當(dāng)sum == S時(shí),方案數(shù)+1。最終返回方案數(shù)。

LeetCode491 遞增子序列

題目

給定一個(gè)整型數(shù)組, 你的任務(wù)是找到所有該數(shù)組的遞增子序列,遞增子序列的長(zhǎng)度至少是2。

示例:

輸入: [4, 6, 7, 7]

輸出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]]

說(shuō)明:

給定數(shù)組的長(zhǎng)度不會(huì)超過(guò)15。

數(shù)組中的整數(shù)范圍是 [-100,100]。

給定數(shù)組中可能包含重復(fù)數(shù)字,相等的數(shù)字應(yīng)該被視為遞增的一種情況。

C++代碼

class Solution {

public:

set> res; //使用set 實(shí)現(xiàn)去除重復(fù)的功能

vector> findSubsequences(vector& nums) {

vector> ans; //最終結(jié)果

vector path; //每一次遍歷的路徑

//對(duì)數(shù)組中的每一個(gè)元素都要dfs

for(int i=0;i

dfs(nums,path,i);

}

//將set中的數(shù)據(jù)轉(zhuǎn)換到vector

set>::iterator it; //迭代器

for(it=res.begin();it!=res.end();it++){

ans.push_back(*it);

}

return ans;

}

void dfs(vector nums,vector path,int pos){

//如果path的大小為0,則證明這是第一個(gè)數(shù)據(jù),直接放入

if(path.size()==0) path.push_back(nums[pos]);

//向后遍歷,逐個(gè)添加

for(int i=1;i

//如果待添加的值小于path的最后一個(gè)值 不添加,如果 當(dāng)前的位置大于數(shù)組長(zhǎng)度 證明 nums已經(jīng)遍歷完 此時(shí)continue其實(shí)就是return了

if(nums[pos+i]nums.size()-1)) continue;

path.push_back(nums[pos+i]);//path放入新數(shù)據(jù)

res.insert(path); //將path添加進(jìn)set

dfs(nums, path, pos + i); //對(duì)新的數(shù)據(jù)再進(jìn)行dfs

path.pop_back(); //回溯

}

}

};

體會(huì)

求一個(gè)序列中的所有遞增子序列。首先區(qū)分一下子序列與子串,子序列中的數(shù)字不需要是連續(xù)的,子串的數(shù)字是連續(xù)的。因?yàn)閿?shù)據(jù)中不能有重復(fù),我們使用set來(lái)達(dá)到這一效果。dfs內(nèi)部,path表示當(dāng)前的路徑,pos表示當(dāng)前的位置。思路很清晰,我們從當(dāng)前數(shù)據(jù)開(kāi)始,對(duì)其后面的每一個(gè)數(shù)據(jù)做插入操作后,繼續(xù)dfs,知道完成整個(gè)序列。注意回溯。

LeetCode515 在每個(gè)樹(shù)行中找最大值

題目

您需要在二叉樹(shù)的每一行中找到最大的值。

示例:

輸入:

1

/ \

3 2

/ \ \

5 3 9

輸出: [1, 3, 9]

C++代碼

class Solution {

public:

map> hash; //key為樹(shù)的深度 vector存放該層的數(shù)據(jù)

vector largestValues(TreeNode* root) {

dfs(root,0);

vector res;

for(auto key : hash){

res.push_back(*max_element(key.second.begin(),key.second.end())); //將每一行的最大值存在res中

}

return res;

}

void dfs(TreeNode* root,int depth){

if(!root) return;

hash[depth].push_back(root->val); //將當(dāng)前節(jié)點(diǎn)存在hash中對(duì)應(yīng)層的數(shù)組中

if(root->left) dfs(root->left,depth+1); //遍歷左孩子

if(root->right) dfs(root->right,depth+1); //遍歷右孩子

}

};

體會(huì)

思路很清晰,map的key表示第幾層,value表示對(duì)應(yīng)的節(jié)點(diǎn)。我們使用DFS的方法遍歷整個(gè)樹(shù)。遍歷的過(guò)程中,記錄下每一個(gè)節(jié)點(diǎn)的深度,將每一層的節(jié)點(diǎn)都存在map中對(duì)應(yīng)數(shù)組中。最后將每一層最大的數(shù)據(jù)存儲(chǔ)來(lái)即可。

LeetCode513 找樹(shù)左下角的值

題目

給定一個(gè)二叉樹(shù),在樹(shù)的最后一行找到最左邊的值。

示例 1:

輸入:

2

/ \

1 3

輸出:

1

示例 2:

輸入:

1

/ \

2 3

/ / \

4 5 6

/

7

輸出:

7

C++代碼

class Solution {

public:

map> hash;

int max_depth = INT_MIN; //初始化最大深度為一個(gè)極小值

int findBottomLeftValue(TreeNode* root) {

dfs(root,0); //從根節(jié)點(diǎn)開(kāi)始dfs

return hash[max_depth][0]; //將最底下一層最左邊的元素返回出來(lái)

}

void dfs(TreeNode* root,int depth){

if(!root) { // 如果是葉節(jié)點(diǎn)下面的節(jié)點(diǎn) 對(duì)最大深度作出修改

if(depth-1>max_depth) max_depth=depth-1;

return;

}

hash[depth].push_back(root->val); //將對(duì)應(yīng)層的節(jié)點(diǎn)依次放入

dfs(root->left,depth+1); //dfs左子樹(shù)

dfs(root->right,depth+1); //dfs右子樹(shù)

}

};

體會(huì)

這個(gè)題跟上一個(gè)題的思路完全一致,沒(méi)有任何區(qū)別。唯一的不同就在于我們這一次不需要將一行中的最大值求出來(lái),我們只需要返回最左邊的那個(gè)值就可以了。

總結(jié)

以上是生活随笔為你收集整理的c语言中dfs用pos做参数,LeetCode算法练习——深度优先搜索 DFS(2)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。