问题描述
问题分析
分析题目,全排列问题都是用经典的回溯法,这里可以结合46题一起看,多思考思考这里的减支思想:
在处理数组中重复元素的时候,要先将数组排序,排序以后在数组重复元素都相邻在一起。造成重复结果的原因是
当前元素和前一个元素是相同的,并且选完当前元素后,前一个元素还可以选
。即:
- 第一次取是先选了前一个元素,然后又选了当前这个元素(两者相同),形成一个解;
- 由于回溯,第二次取的时候,先取了当前元素,然而前一个元素(两者相同)还可以选,这样便形成了相同解。
按照这种减支思想,我们减支的条件是:
- 不是第一个分支
- 当前元素与前一个元素相同
- 前一个元素可选
解法:回溯法
Java代码
package com.company;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
int[] a = {1, 1, 2};
List<List<Integer>> result = permuteUnique(a);
System.out.println(11);
}
static public List<List<Integer>> permuteUnique(int[] nums) {
//排序
Arrays.sort(nums);
List<List<Integer>> result = new ArrayList<>();
boolean[] visit = new boolean[nums.length];
backtrace(result, nums, new ArrayList<>(), visit);
return result;
}
private static void backtrace(List<List<Integer>> result, int[] nums, ArrayList<Integer> temp, boolean[] visit) {
//结束条件
if (temp.size() == nums.length){
result.add(new ArrayList<>(temp));
}
//回溯
for (int i = 0; i < nums.length; i++) {
if (!visit[i]){
//减支
if ( (i > 0) && (nums[i] == nums[i-1]) && (!visit[i-1])){
continue;
}
//做选择
visit[i] = true;
temp.add(nums[i]);
//backtrace
backtrace(result, nums, temp, visit);
//撤销选择
visit[i] = false;
temp.remove(temp.size() - 1);
}
}
}
}
结果分析
以上代码的执行结果:
执行时间 | 内存消耗 |
---|---|
2 ms | 38.1 MB |
版权声明:本文为G_drive原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。