Day 29 | 回溯 491.递增子序列 、 46.全排列 、47.全排列 II

491.递增子序列

题目
文章讲解
视频讲解

思路:去重原则:元素,树层不可以重复取,树枝可以。hash这种去重方式不需要回溯

class Solution {
    List<List<Integer>> result = new ArrayList<>();
    List<Integer> path = new LinkedList<>();

    public List<List<Integer>> findSubsequences(int[] nums) {
        backTracing(nums, 0);
        return result;
    }

    private void backTracing(int[] nums, int startIndex) {
        if (path.size() > 1) {
            result.add(new ArrayList(path));
        }
        HashSet<Integer> hash = new HashSet<>();
        for (int i = startIndex; i < nums.length; i++) {
            if (!path.isEmpty() && path.get(path.size() - 1) > nums[i] || hash.contains(nums[i]))//path不为空且比nums中元素大或者之前已在本树层存在过
                continue;//后续还要接着进行比较
            hash.add(nums[i]);//只记录每层的元素是否用过
            path.add(nums[i]);
            backTracing(nums, i + 1);
            path.removeLast();
        }
    }
}

46.全排列

题目
文章讲解
视频讲解

思路:used[i]这种去重方式需要回溯
注意比较两种去重方式 permute(排列)

class Solution {
    List<List<Integer>> result = new ArrayList<>();
    List<Integer> path = new LinkedList<>();
    boolean[] used;

    public List<List<Integer>> permute(int[] nums) {
        if (nums.length == 0)
            return result;
        used = new boolean[nums.length];
        permuteHelper(nums);
        return result;
    }

    private void permuteHelper(int[] nums) {
        if (path.size() == nums.length) {
            result.add(new ArrayList(path));
            //return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (used[i])
                continue;
            used[i] = true;
            path.add(nums[i]);
            permuteHelper(nums);
            path.removeLast();
            used[i] = false;
        }
    }
}

47.全排列 II

题目
文章讲解
视频讲解

思路:去重之前一定做排序,used[i-1] == false(对树层进行去重(视频中讲是一个回溯过程,但还需再理解))或used[i-1] == true(对树枝进行去重)

class Solution {
    List<List<Integer>> result = new ArrayList<>(); // 存储最终结果的列表
    List<Integer> path = new LinkedList<>(); // 存储当前路径的列表
    boolean[] used; // 用于标记元素是否被使用过的布尔数组

    public List<List<Integer>> permuteUnique(int[] nums) {
        used = new boolean[nums.length]; // 初始化used数组
        Arrays.fill(used, false); // 将used数组全部初始化为false
        Arrays.sort(nums); // 对输入数组进行排序
        permuteHelper(nums, used); // 调用辅助方法进行排列
        return result; // 返回最终结果
    }

    private void permuteHelper(int[] nums, boolean[] used) {
        if (path.size() == nums.length) { // 如果当前路径长度等于输入数组长度
            result.add(new ArrayList<>(path)); // 将当前路径添加到最终结果中
            return; // 返回
        }
        for (int i = 0; i < nums.length; i++) { // 遍历输入数组
            if (i > 0 && nums[i] == nums[i - 1] && used[i-1] == false) // 如果当前元素与前一个相同且前一个未被使用
                continue; // 跳过当前循环
            if(used[i] == false){ // 如果当前元素未被使用
                used[i] = true; // 标记当前元素为已使用
                path.add(nums[i]); // 将当前元素添加到路径中
                permuteHelper(nums, used); // 递归调用辅助方法
                path.removeLast(); // 移除路径中的最后一个元素
                used[i] = false; // 标记当前元素为未使用
            }
        }
    }
}

class Solution {
    List<List<Integer>> result = new ArrayList<>();
    List<Integer> path = new LinkedList<>();
    boolean[] used;

    public List<List<Integer>> permuteUnique(int[] nums) {
        used = new boolean[nums.length];
        Arrays.fill(used, false);
        Arrays.sort(nums);
        permuteHelper(nums, used);
        return result;
    }

    private void permuteHelper(int[] nums, boolean[] used) {
        if (path.size() == nums.length) {
            result.add(new ArrayList<>(path));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (i > 0 && nums[i] == nums[i - 1] && used[i-1]==true)
                continue;
            if(used[i] == true) continue;//used出现过便不可再取
            used[i] = true;
            path.add(nums[i]);
            permuteHelper(nums, used);
            path.removeLast();
            used[i] = false;
        }
    }
}

你可能感兴趣的:(二月红,java,力扣,算法)