1. 程式人生 > >leetcode-回溯演算法總結

leetcode-回溯演算法總結

leetcode-17-電話號碼的字母組合(letter combination of a phone number)-java

在類中建立一個數字對應字母的map,和對應的結果list
進入combine("",digits)
第一個字串為當前字串,後面的為還能加上的數字字串
每次從陣列字串中取最前一位,得到對應的char陣列,將nowStr+對應的陣列(用for迴圈,分別加幾次),然後再次combine
如果remain為“”,說明一小次迴圈完成,將nowstr加入result
可以將hashmap 改為char[][]陣列,每個數字的字母放在對應的地方

leetcode-22-括號生成(generate parentheses)-java

nowstr為當前字串,left為剩下的左括號,right為剩下的右括號
如果right>left說明左邊已經有多的( 接下來))或者()都可以,可以加右括號
如果left>0說明left有多的,可以加左括號
如果left=right=0 說明此次結束,加入result

leetcode-46-全排列(permutations)-java

解法1(成功,8ms,較慢)

在類中建立一個result的變數,放置結果
建立permutateRemain函式,變數為上一次的全排列幾位的list(now)和還能排的數字的list(remain)
在函式中,
如果remain剩餘的量為0,將now加入result
對remain進行遍歷,在遍歷中
遍歷的數字為now
先建立一個對now的copy newlist,將newlist加入now
然後將remain除去now,進行新的permutateRemain,然後在remain重新加入now,結束遍歷

解法2(別人的)

省去了不斷copy list的時間,加了判斷now有無這個num的時間

解法3,解法4

字典序 的非遞迴全排列

遞迴的交換全排列

http://www.cnblogs.com/pmars/archive/2013/12/04/3458289.html

https://segmentfault.com/a/1190000007067885

 

leetcode-78-子集(subsets)-java

解法1(別人的)

不錯的方法

https://blog.csdn.net/wodedipang_/article/details/52996928

使用位操作,不使用遞迴。首先,計算一下該陣列nums一共有多少個子集,設陣列nums的長度為n,那麼它的子集總數為num=2^n。
設定一個變數index,其初始值為1。那麼從0到2^n-1中數,對於每一個數i,用index(從1到10,100,100(2進位制))與這個i進行與操作,如果得出的結果大於0,則把該數輸入到List<>中取,比較n次,因為陣列的長度為n。

解法2(別人的)

回溯演算法

這道題需要求給定陣列的子集,特別要求有:
1、必須是升序
2、不能出現重複的

所以做法其實也就是,首先排序,然後回溯。。和昨天那題一樣,可以回去看一下。記得選擇下一個的時候,別和當前的值重複就可以了。

解法3(別人的)

回溯演算法|遞迴實現

本解法採用回溯演算法實現,回溯演算法的基本形式是“遞迴+迴圈”,正因為迴圈中巢狀著遞迴,遞迴中包含迴圈,這才使得回溯比一般的遞迴和單純的迴圈更難理解,其實我們熟悉了它的基本形式,就會覺得這樣的演算法難度也不是很大。原陣列中的每個元素有兩種狀態:存在和不存在。

① 外層迴圈逐一往中間集合 temp 中加入元素 nums[i],使這個元素處於存在狀態

② 開始遞迴,遞迴中攜帶加入新元素的 temp,並且下一次迴圈的起始是 i 元素的下一個,因而遞迴中更新 i 值為 i + 1

③ 將這個從中間集合 temp 中移除,使該元素處於不存在狀態

解法4(別人的)

組合|非遞迴實現

這種方法是一種組合的方式

① 最外層迴圈逐一從 nums 陣列中取出每個元素 num

② 內層迴圈從原來的結果集中取出每個中間結果集,並向每個中間結果集中新增該 num 元素

③往每個中間結果集中加入 num

④將新的中間結果集加入結果集中

 

leetcode-79-單詞搜尋(word search)-java

解法1(成功,15ms,很快)

使用回溯演算法,對board中每個與word首字母相同的字元ij,開啟begin函式
begin中
如果result已經為true,不再繼續
如果char[i][j]與word首字母不同,不再繼續
如果相同,
如果word長度為1,說明已經到最後一步,result=true
否則,char[i][j]='*',因為讓接下來的操作不到這一位
然後newWord=word截去首位的字串
然後根據i,j的位置,對上下左右進行begin
最後char[i][j]=now,恢復
別人的解法有的把char[i][j]='*',換成一個boolean二維陣列,記錄跑過的地方