代码随想录算法训练营 day 29: * 491.递增子序列 * 46.全排列 * 47.全排列 II

65 阅读1分钟

491. Non-decreasing Subsequences

非递减子序列。显然要用一个set来保存已经取过的元素。而且在本层内,元素取完不能再取,所以set需要是本地的。 491. 递增子序列1

另外要注意细节,题目要求返回的子序列至少两个元素。

class Solution {
    public void backtracking(LinkedList<Integer> path, int[] nums, int pos, List<List<Integer>> res) {
        if(path.size() >= 2) {
            res.add(new LinkedList<Integer>(path));
        }

        Set<Integer> uset = new HashSet<Integer>();

        for(int i=pos; i< nums.length; i++) {
            if(!path.isEmpty() && nums[i] < path.peekLast()
               || uset.contains(nums[i])) {
                   continue;

            }
            uset.add(nums[i]);
            path.add(nums[i]);
            backtracking(path, nums, i+1, res);
            path.removeLast();
        }
    }
    public List<List<Integer>> findSubsequences(int[] nums) {
        List<List<Integer>> res = new LinkedList<List<Integer>>();
        LinkedList<Integer> path = new LinkedList<Integer>();

        if(nums.length == 0) {
            return res;
        }

        backtracking(path, nums, 0, res);

        return res;
    }
}

46. Permutations 排列题目以前刷过还记得。一条子树上要记录已经取过的元素,要么用全局变量,要么递归带一个额外的数组下去。

class Solution {
    public void backtracking(LinkedList<Integer> path, Set<Integer> uset, int[] nums, List<List<Integer>> res) {
        if(path.size() == nums.length) {
            res.add(new LinkedList<Integer>(path));
            return;
        }

        
        for(int i=0; i<nums.length; i++) {
            if(uset.contains(nums[i])) {
                continue;
            }

            path.add(nums[i]);
            uset.add(nums[i]);
            backtracking(path, uset, nums, res);
            path.removeLast();
            uset.remove(nums[i]);
        }

    }
    public List<List<Integer>> permute(int[] nums) {
        Set<Integer> uset = new HashSet<Integer>();
        List<List<Integer>> res = new LinkedList<List<Integer>>();
        LinkedList<Integer> path = new LinkedList<Integer>();

        if(nums.length == 0) {
            return res;
        }

        backtracking(path, uset, nums, res);

        return res;
    }
}

47. Permutations II 带去重的排列。但去重判断既可以true也可以false,我是没想过的。虽然第一次写的是按层去重,即

if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {
    continue;
}

但没想过也可以把true改为false也能过,只是变成了在树枝上去重。

if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == true) {
    continue;
}

树层上去重(used[i - 1] == false),的树形结构如下:

47.全排列II2

树枝上去重(used[i - 1] == true)的树型结构如下:

47.全排列II3

class Solution {
    boolean[] used;
    public void backtracking(LinkedList<Integer> path, int[] nums, List<List<Integer>> res) {
        if(path.size() == nums.length) {
            res.add(new LinkedList<Integer>(path));
            return;
        }

        for(int i=0; i<nums.length; i++) {
            if(used[i] || (i>0 && nums[i] == nums[i-1] && !used[i-1])) {
                continue;
            }

            used[i] = true;
            path.add(nums[i]);
            backtracking(path, nums, res);
            path.removeLast();
            used[i] = false;
        }
    }
    public List<List<Integer>> permuteUnique(int[] nums) {
        
        Arrays.sort(nums);
        used = new boolean[nums.length];
        List<List<Integer>> res = new LinkedList<List<Integer>>();
        LinkedList<Integer> path = new LinkedList<Integer>();

        if(nums.length == 0) {
            return res;
        }

        backtracking(path, nums, res);

        return res;
    }
}