如何思考剪枝过程?
- 数组中有重复数字会导致出现重复的排列,因为要对原数组循环遍历每个数字来递归获取排列数。
- 要阻止出现重复排列的情况,就要在同一层循环中不使用重复的数字来递归,为了方便判断是否为重复的数字,可以先对数组进行排序,再判断相邻的两个数字是否重复即可。
- used数组用于判断某个数字是否被使用过,如果被使用过则跳过这个数字避免重复使用。但在重复数字的场景下,如果数字没被使用过还需要判断他是否是跟前一个数字重复,如果重复了也要跳过这个数字。
- used数组只在递归过程会逐个变true,如果used[i-1]为false说明和当前数字相同的上一个数字在上一次循环中被递归使用了,回溯后当前层为false,所以如果当前数字和前一个数字相同,就不能再选择这个数字进入递归。
- 因为要判断两个相邻的数字,所以起码要从第二个数字开始判断,即i>0。
参考
https://blog.nowcoder.net/n/50274e5a9c4142be9fa551fba14b6f6a?f=comment
/**
*
* @param num int整型一维数组
* @return int整型二维数组
*/
function permuteUnique( num ) {
const ret = []
const used = Array.from(num, (item) => item = false); // 用于判断数组中的元素是否使用过,如果使用过则跳过当前元素
num.sort(); // 为了能方便的判断两个相邻数字是否相同,需要先对数组进行排序
// write code here
function dfs(num, ansArray=[]) {
if (ansArray.length === num.length) {
ret.push(ansArray.slice()); // 要传入一个副本,也可以用[...ansArray]
return;
}
for (let i = 0; i < num.length; ++i) {
// 有重复数字后会导致出现重复的排列,要阻止这种情况则必须要同一层中重复数字不能重复递归使用,关键是如何判断同一层重复数字的逻辑。
// used数组只在递归过程会逐个变true,如果当前为true上一个为false说明这是同一层循环中的上一次循环回溯后变false了,此时两者在同一层。
// 因为要判断两个相邻的数字,所以起码要从第二个数字开始判断,即i>0
if (used[i] || (i > 0 && num[i-1] === num[i] && !used[i-1])) {
continue;
}
ansArray.push(num[i]);
used[i] = true;
dfs(num, ansArray); // 递归传入的是原数组,通过判断原数组的元素是否使用过来缩减元素范围,而不是通过传入削减后的数组切片,这样会丢失元素
used[i] = false;
ansArray.pop();
}
}
dfs(num, []);
return ret;
}
module.exports = {
permuteUnique : permuteUnique
};
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param num int整型一维数组
* @return int整型ArrayList<ArrayList<>>
*/
private ArrayList<ArrayList<Integer>> res = new ArrayList<>();
public ArrayList<ArrayList<Integer>> permuteUnique (int[] num) {
// write code here
boolean[] used = new boolean[num.length];
ArrayList<Integer> arr = new ArrayList<Integer>();
Arrays.sort(num);
dfs(num, arr, used);
return this.res;
}
private void dfs(int[] num, ArrayList<Integer> arr, boolean[] used) {
if (num.length == arr.size()) {
this.res.add(new ArrayList<Integer>(arr));
return;
}
for (int i = 0; i < num.length; ++i) {
if (used[i] || (i > 0 && num[i] == num[i-1] && used[i-1] == false)) {
continue;
}
arr.add(num[i]);
used[i] = true;
dfs(num, arr, used);
used[i] = false;
arr.remove(arr.size()-1);
}
}
}



京公网安备 11010502036488号