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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

leetcode之回溯backtracing专题2

發布時間:2023/12/10 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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]。
 

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;int j = i + 1;for (; j < nums.length; j++){if (nums[j] != nums[j - 1]) {i = j - 1;break;}}if(j==nums.length){break;}}}

 改成這樣就對了。但是這樣代碼不夠優雅。

處理情況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已經選過一個值了。
 

boolean selected = false;for(int i=0;i<nums.length;i++){if(p[i]==false && (!selected || (nums[i]!=newarray[idx]))){selected = true;newarray[idx]=nums[i];p[i]=true;robot(idx+1,newarray,nums);p[i]=false;}}

處理情況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的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。