LeetCode.46 & 47 全排列

11 篇文章 0 订阅
  1. Permutataion
    Algs:

基础回溯算法,列出每种可能性, 剪枝直接在每次递归最后撤销选择即可。

public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        List<Integer> list = new ArrayList<>();
        backTrack(list, res, nums);
        return res;
    }
    private void backTrack(List<Integer> list, List<List<Integer>> res, int[] nums) {
    	// base case : cuz we have to consider every situation of permutations, so if the list has 3 elements, add it into the res list.
    	if (list.size() == nums.length) res.add(new ArrayList<Integer>(list));
    	for (int num : nums) {
    		// visit the element
    		if (!list.contains(num)) {
    			list.add(num);
    			// dfs the other element
    			backTrack(list, res, nums);
    			// remove this choice
    			list.remove(list.size() - 1);
    		}
    	}
    }
  1. permutationsII
    相较于46题, 47题包含重复元素的情况,结果中也不能包含相同的数组,因此为剪枝增加了难度。
    algs:
  2. DFS:(1)直接用复杂度O(n)的list.contains方法去重;代码如下:
class Solution {
    
    public List<List<Integer>> permuteUnique(int[] nums) {
        boolean[] visited = new boolean[nums.length];
        List<List<Integer>> res = new ArrayList<>();
        List<Integer> list = new ArrayList<>();
        backtrack(res, list, nums, visited);
        return res;
    }
    private void backtrack(List<List<Integer>> res, List<Integer> list, int[] nums, boolean[] v) {
        if (list.size() == nums.length && !res.contains(list)) res.add(new ArrayList<>(list));
        for (int i = 0; i < nums.length; i++) {
            if (!v[i]) {
                v[i] = true;
                list.add(nums[i]);
                backtrack(res, list, nums, v);
                list.remove(list.size() - 1);
                v[i] = false;
            }
        }
    }
}
  1. DFS优化, 先将数组排序,然后去重;
class PermutationsTwo {
    public List<List<Integer>> permuteUnique(int[] nums) {
    	boolean[] visited = new boolean[nums.length];
    	List<List<Integer>> res = new ArrayList<>();
    	List<Integer> list = new ArrayList<>();

        Arrays.sort(nums);
        backtrack(list, res, nums, visited);
        return res;
    }
    private void backtrack(List<Integer> list, List<List<Integer>> res, int[] nums, boolean[] visited) {
    	// base case
    	if (list.size() == nums.length) res.add(new ArrayList<>(list));
    	// backtrack
    	for (int i = 0 ; i < nums.length; i++) {
    		// 这里用!visited 和 visited都可以得出结论,!visited意味先前那个数已经被选择过了,
    		// 以相同数为开头元素的组合已经被加进去了, i位置是第一次被选,在他的递归中还要在加进去i-1的元素,因为他没有被visit
    		if (!visited[i]) {
    			if (i != 0 && nums[i] == nums[i - 1] && !visited[i-1]) continue;
    			visited[i] = true;
    			list.add(nums[i]);
    			list.remove(list.size() - 1);
    			visited[i] = false;
     		}
    	}
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值