LeetCode刷題Medium篇Permutations全排列----回溯法backtracking
阿新 • • 發佈:2018-12-21
題目
Given a collection of distinct integers, return all possible permutations.
Example:
Input: [1,2,3]
Output:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
注意,不同的整數,相同可能有變化
十分鐘嘗試
應該是缺少這些問題的思路,直接看思路,果然回溯法。先看看回溯法是什麼意思
回溯法
backtracking(回溯法)是一類遞迴演算法,通常用於解決某類問題:要求找出答案空間中符合某種特定要求
回溯法的核心模型是一個決策樹,每個節點的子節點代表該節點的選項。從根節點出發,作出某種選擇達到節點A,隨後會面臨節點A的選項,重複這個過程直到達到葉節點。如果途中發現某節點B的狀態已經不符合要求,那麼棄掉以B為根節點的子決策樹。
到達葉節點時,判斷其是否符合問題要求,然後根據情況作相應處理(如將符合要求的葉節點加入一個list)。葉節點沒有子節點,因此回溯到上一個訪問過的節點
在上圖的決策樹中,用good和bad分別代表符合和不符合要求的葉節點。回溯法的遍歷過程是這樣的:
- 從Root開始,有A和B兩個選項。選擇A。
- 從A開始,有C和D兩個選項。選擇C。
- C不符合要求,回溯到A。
- A處的剩餘選項為D。選擇D。
- D不符合要求,回溯到A。
- A的選項已窮盡,回溯到Root。
- Root處的剩餘選項為B。選擇B。
- 從B開始,有E和F兩個選項。選擇E。
- E符合要求,將其加入某個list,回溯到B。
- B出的剩餘選項為F。選擇F。
- F不符合要求。回溯到B。
- B的選項已窮盡,回溯到Root。
- Root的選項已窮盡。結束。
本文給出leetcode上陣列排列組合問題的回溯法解答。這些問題大多為“返回某陣列/字串的所有排列/組合”型別,沒有提出明確的要求來篩選葉節點。看起來,似乎簡單地使用回溯法遍歷決策樹即可,但是在實現中會遇到一些棘手的小問題,比如每一個選項如何定義,如何記錄某一個節點上已經選擇過的選項等。學習回溯法時,可以先從這些問題開始熟悉回溯法的套路,熟練後再去解決更復雜的問題。
正確解法
雖然看了回溯法,但是這個題目作者說用的回溯法,感覺更像是遞迴。程式碼不容易理解,我手寫了下面的過程,方便大家理解,先看圖:
程式碼如下:
class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> list=new ArrayList();
backTrace(list,new ArrayList(),nums);
return list;
}
private void backTrace(List list,List<Integer> tmpList,int[] nums){
if(tmpList.size()==nums.length){
//全域性返回的list就在這新增元素,其他地方都是tmplist
list.add(new ArrayList(tmpList));
}
else{
for(int i=0;i<nums.length;i++){
if(tmpList.contains(nums[i])){
continue;
}
tmpList.add(nums[i]);
backTrace(list,tmpList,nums);
tmpList.remove(tmpList.size()-1);
}
}
}
}