「这是我参与2022首次更文挑战的第29天,活动详情查看:2022首次更文挑战」
前言
今天我们继续研究算法,还是那句话,程序中最伤脑筋的就算法,写算法不比CURD,都所有情况都考虑进去才行,那么接下来我们再来看看这道题怎么解决。
一.题目,来源LeetCode回溯算法第47题
给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
*
* 输入: [1,1,2]
* 输出:
* [
* [1,1,2],
* [1,2,1],
* [2,1,1]
* ]
二.解题思路
1.全排列
从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。
2.思路
既然题目是属于回溯算法类的,那肯定得抓住回溯点才能解决问题,该题的关键点至于不重复的全排列,而题目要求的是不重复那就得涉及到元素的去重,我们可以先对数组元素进行去重然后再对去重后的剩余元素进行全排列,即可满足答案。
三.解题
1.具体方法
public static List<List<Integer>> result = new LinkedList<>();
public static List<List<Integer>> permuteUnique(int[] nums) {
if(nums.length == 0){
return result;
}
//首先给数组排序
Arrays.sort(nums);
findUnique(nums,new boolean[nums.length],new LinkedList<Integer>());
return result;
}
public static void findUnique(int[] nums, boolean[] visited,LinkedList<Integer> trace){
//结束条件
if(trace.size() == nums.length){
result.add(new LinkedList(trace));
return ;
}
//选择列表 1 1 2
for(int i = 0; i<nums.length; i++){
//其次,我们已经选择过的不需要再放进去了
if(visited[i]) continue;
//接下来,如果当前节点与他的前一个节点一样,并其他的前一个节点已经被遍历过了,那我们也就不需要了。
if(i>0 && nums[i] == nums[i-1] && visited[i-1]) continue;
//做出选择
trace.add(nums[i]);
visited[i] = true;
//回溯点 继续查找
findUnique(nums,visited,trace);
//撤销选择
trace.removeLast();
visited[i] = false;
}
}
2.执行及结果
public static void main(String[] args) {
int a[] = new int[]{1,1,2};
permuteUnique(a);
System.out.println(result);
}
小结
LeetCode里回溯类的算法题都很有意思,需要用到的知识点也很多,我这里只是为了解题而解题,练习这种思维方式,没有过多的去考虑时间和空间复杂度,实际上算法的话对这两方面要求都很高,这点后期也会陆续跟上。