leetcode46.全排列
阿新 • • 發佈:2019-12-31
給定一個沒有重複數字的序列,返回其所有可能的全排列。
示例:
輸入: [1,2,3] 輸出: [ [1,3], [1,3,2], [2,1,1], [3,1] ]
來源:力扣(LeetCode) 連結:leetcode-cn.com/problems/pe… 著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。
兩種解法,一種回溯,一種字典序。
回溯:比較簡單,直接上程式碼
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
//回溯法
//per(0,nums,result);
return result;
}
//回溯
private void per(int cur,int[] nums,List<List<Integer>> result){
//cur指標走到陣列最後,記錄值,並返回
if(cur == nums.length-1){
add(nums,result);
return;
}
//固定一位後,遞迴交換下一位
for(int i = cur;i<nums.length;i++){
//交換
swap(cur,i,nums);
//遞迴
per(cur+1,result);
//回溯
swap(cur,nums);
}
}
private void add(int[] nums,List<List<Integer>> result){
List<Integer> list = new ArrayList<>();
for (int i = 0;i<nums.length;i++){
list.add(nums[i]);
}
result.add(list);
}
//對換
private void swap(int i,int j,int[] nums){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
複製程式碼
字典序:
通過字典序演演算法來獲得下一個字典序,但需要先從小到大排序。
字典序演演算法:
(1)從右向左找到第一個下標為i,其中nums[i]<nums[i+1],記錄i
(2)從右向左找到第一個比i大的數,下標為j,交換i,j,
(3)此時i+1之後的數字為從大到小排列,翻轉i+1至陣列末尾的資料,得到下一個排列。
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
//字典序演演算法
Arrays.sort(nums);
add(nums,result);
while(getNextDictionaryPreface(nums)){
add(nums,result);
}
return result;
}
private void add(int[] nums,List<List<Integer>> result){
List<Integer> list = new ArrayList<>();
for(int i = 0;i<nums.length;i++){
list.add(nums[i]);
}
result.add(list);
}
//對換
private void swap(int i,int[] nums){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
//得到下一個字典序
private boolean getNextDictionaryPreface(int[] nums){
//如果長度為1,則沒有下一個字典序
if(nums.length<=1 || nums == null) return false;
//從右到左找到第一個左邊小於右邊的數,並記錄
int jiluleft = -1;
for (int i = nums.length-2; i>=0 ;i--){
if(nums[i] < nums[i+1]){
jiluleft = i;
break;
}
}
//若jiluleft值不變,說明沒有下一個字典序,例如{4,1}
if(jiluleft == -1)
return false;
else{
//從右到左找到第一個大於nums[jiluleft]的數,並交換
for (int i = nums.length-1; i>=jiluleft ;i--){
if(nums[i] > nums[jiluleft]){
swap(jiluleft,nums);
break;
}
}
//翻轉left+1至陣列末尾
reversalNums(jiluleft+1,nums.length-1,nums);
return true;
}
}
//翻轉陣列
private void reversalNums(int left,int right,int[] nums){
while(right > left){
swap(left,right,nums);
left++;right--;
}
}
複製程式碼