leetcode之回溯backtracing专题2
46 Permutations
輸入一個不重復的數組 ,寫出這個數組的排列,不能重復。
例如 輸入nums=[1,2,3],輸出
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
思路:可以看到 第0位(從左開始數)有nums.length個數字可以選擇:1,2,3,在第0位確定以后,第1位有nums.length-1個數字可以選擇,例如p[0] = 1,p[1]只可能為2 或者3。所以重要的是記錄哪些下標的元素已經被選擇過。
public class Solution {private boolean[] p;//記錄選中過的下標private List<List<Integer>> list;public List<List<Integer>> permute(int[] nums) {int[] newarray=new int[nums.length];//存放選中的數字p = new boolean[nums.length];list = new ArrayList<List<Integer>>();robot(0,newarray,nums);return list;}public void robot(int idx,int[] newarray,int[] nums){if(idx>=nums.length){List<Integer> l = new ArrayList<Integer>();for(int i=0;i<newarray.length;i++){l.add(newarray[i]);}list.add(l);return;}for(int i=0;i<nums.length;i++){if(p[i]==false){newarray[idx]=nums[i];p[i]=true;robot(idx+1,newarray,nums);p[i]=false;}}} }47 Permutations II
輸入一個重復的數組 ,寫出這個數組的排列,不能重復。
例如輸入 [1,1,2] 輸出
[
[1,1,2],
[1,2,1],
[2,1,1]
]
思路:這與46的區別是輸入的數組中有重復的數字。如果按照46的思路做,會出現重復的結果。我們先按照46的來做一下吧。用”數字(下標)”這種方式表示數組元素:1(0) 1(1) 2(2)。這樣才能把相同的數字區分開來。為了方便,我們先將輸入的數組排序。按照46的思路得到以下組合:
1(0) 1(1) 2(2)
1(0) 2(2) 1(1)
1(1) 1(0) 2(2)
1(1) 2(2) 1(0)
2(2) 1(0) 1(1)
2(2) 1(1) 1(0)
重點標記的是重復的元素。分析一下。第0位可以選擇的元素有 nums[0], nums[1], nums[2],但是當已經選擇nums[0]之后,再遇到nums[1]=nums[0]的時候,nums[1]是不能選擇的,否則就重復了。所以第0位可以選擇的元素有 nums[0], nums[2]。每一位都是,判斷nums[idx]能不能選擇標準是nums[idx-1]=nums[idx]是否為true。
這個判斷怎么加呢?下面記錄一下我自己犯過的錯。
處理情況1
for(int i=0;i<nums.length;i++){if(p[i]==false){newarray[idx]=nums[i];p[i]=true;robot(idx+1,newarray,nums);p[i]=false;for (int j = i + 1; j < nums.length; j++){if (nums[j] != nums[j - 1]) {i = j - 1;break;}}}} 每到一個位置,先選擇一個元素,再處理下一個元素和前面的元素是否相同。這里判斷的時候沒有考慮前面的元素是否會選中,可能會有多余的操作。更重要的是沒有處理如果重復元素是最后一個元素怎么處理。失敗用例:[1,1]。
改成這樣就對了。但是這樣代碼不夠優雅。
處理情況2
for(int i=0;i<nums.length;i++){if(p[i]==false && (i==0 || (nums[i]!=newarray[idx]))){newarray[idx]=nums[i];p[i]=true;robot(idx+1,newarray,nums);p[i]=false;}} 因為newarray[idx]記錄了上一次選擇的值,所以想到只要判斷這次的候選值nums[i]和newarray[idx]不同就好了。這次的錯誤是因為i==0的判斷是有誤的。因為不一定每次都是nums[0]是第一個被選中的。例如當第0位選擇nums[0],在選第2位的時候第一個被選中的一定是nums[1] ,所以這里應該用一個boolean變量表示本次是不是對idx已經選過一個值了。
處理情況3
接著我還用了一種方式處理。使用了一個單獨的變量記錄在選擇idx的候選值時候,上一個選擇的值。
int preNum = -1;boolean selected = false;for(int i=0;i<nums.length;i++){if(p[i]==false && (selected==false || (nums[i]!=preNum))){selected = true;preNum = nums[i];newarray[idx]=nums[i];p[i]=true;robot(idx+1,newarray,nums);p[i]=false;}}總結:大概可以在編程的時候行不通。一定是一定可以才可以。在backtracing中最重要的是理解每一步的狀態。
總結
以上是生活随笔為你收集整理的leetcode之回溯backtracing专题2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java学习笔记day14—HTML
- 下一篇: 使用git pull文件时和本地文件冲突