46. 全排列(java實現)--LeetCode
阿新 • • 發佈:2021-01-27
技術標籤:演算法題遞迴算髮題leetcode演算法資料結構java
文章目錄
題目:
給定一個 沒有重複 數字的序列,返回其所有可能的全排列。
示例:
輸入: [1,2,3]
輸出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
解法1:遞迴(換位)
/**
* 思路:
* 放格子,第一個格子放所有的數
* 第二個放除第一個格子外所有的數
* 第三個格子放除1,2格子中的所有的數
* 。。。
* 最後就是所有的可能性
*
* 為了實現上面的效果
* 我們把nums所有的數存入list,之後在其每個位置(格子)上進行交換
* 先和自身換,之後和後面所有的數進行交換。這樣第一個格子就儲存了所有的數
* 對於後面的格子用遞迴,進行同樣的操作
* 最後要把變換後的數換回來,以便下次遞迴不重複
*/
public List<List<Integer>> permute(int[] nums) {
ArrayList<List<Integer>> result = new ArrayList<>();
ArrayList<Integer> list = new ArrayList<>();
for (int num:nums)list.add(num);
backtrack(nums.length,0,list,result);
return result;
}
private void backtrack(int length, int lattice, ArrayList<Integer> list, ArrayList<List<Integer>> result) {
if (lattice==length) {
result.add(new ArrayList<>(list));
return;
}
for (int i=lattice;i<length;i++ ){
Collections.swap(list,lattice,i);
backtrack(length,lattice+1,list,result);
Collections.swap(list,lattice,i);
}
}
時間複雜度:On^2
空間複雜度:On
解法2:
/**
* 和解法1的思路一樣,不過這裡借用了set
* 思路:
* 往格子裡放數,當前格子的數需要遍歷陣列,並且不能是之前放過的
* 因為沒有從重複數字用set來存放之前放過的數。
* 每次遞迴結束就從set和list中移除這個數
*/
public List<List<Integer>> permute(int[] nums) {
ArrayList<List<Integer>> result = new ArrayList<>();
LinkedList<Integer> list = new LinkedList<>();
HashSet<Integer> set = new HashSet<>();
recursive(nums,0,result,list,set);
return result;
}
private void recursive(int[] nums, int lattice, ArrayList<List<Integer>> result, LinkedList<Integer> list, HashSet<Integer> set) {
if (lattice==nums.length){
result.add(new ArrayList<>(list));
return;
}
for (int i:nums){
if (set.add(i)){
list.add(i);
recursive(nums,lattice+1,result,list,set);
list.removeLast();
set.remove(i);
}
}
}
時間複雜度:On^2
空間複雜度:On