NC+LC:全排列

无重复项

题目描述
给定一个不含重复数字的数组nums,返回其 所有可能的全排列
LeetCode中可按任意顺序返回答案,但牛客要求以数字在数组中的位置靠前为优先级,按字典序排列输出。
示例
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

思路


实现代码1

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> res = new ArrayList<List<Integer>>(); //结果集合
        List<Integer> list = new ArrayList<>();
        for(int num : nums){ //将数组元素存入集合,直接对该集合进行处理
            list.add(num);
        }
        backtrack(res, nums.length, list, 0);
        return res;
    }
    public void backtrack(List<List<Integer>> res, int length, List<Integer> list, int start) {
        if (start == length) { //递归终止条件,遍历到了数组末尾
            res.add(new ArrayList<Integer>(list)); //需新建一个集合对象存入
            return;
        }
        for (int i = start; i < length; i++) {
            //将start上的元素依次与后面的元素进行交换
            Collections.swap(list, start, i);
            //递归
            backtrack(res, length, list, start+1);
            //回溯上一个start的位置,保证与其他位置进行同样的交换
            Collections.swap(list, start, i);
        }
    }
}

实现代码2

使用类似深度优先遍历(DFS)的做法
class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> res = new ArrayList<List<Integer>>(); //结果集合
        int[] visited = new int[nums.length]; //标记访问过的位置
        backtrack(res, nums, new ArrayList<Integer>(), visited);
        return res;
    }
    public void backtrack(List<List<Integer>> res, int[] nums, ArrayList<Integer> tmp, int[] visited) {
        if (tmp.size() == nums.length) { //递归终止条件
            res.add(new ArrayList<>(tmp));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (visited[i] == 1) continue;
            visited[i] = 1;
            tmp.add(nums[i]);
            //递归访问没访问过的位置
            backtrack(res, nums, tmp, visited);
            //在回溯过程中还原到上一状态
            visited[i] = 0;
            tmp.remove(tmp.size() - 1);
        }
    }
}

有重复项

题目描述
给定一个可包含重复数字的序列nums,按任意顺序 返回所有不重复的全排列。
示例
输入:nums = [1,1,2]
输出:[[1,1,2],[1,2,1],[2,1,1]]

思路

回溯法(在题目LC 46.全排列的基础进行修改,修改1:先将数组进行排序,使重复元素聚集在一起;修改2:接着通过判断当前元素与前一个元素是否相等,且前一元素是否被访问过来决定是否进行排列)
重点代码:
if (i > 0 && nums[i] == nums[i-1] && visited[i-1] == 0){
    continue;
}

实现代码

class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>> res = new ArrayList<List<Integer>>(); //结果集合
        int[] visited = new int[nums.length]; //标记访问过的位置
        Arrays.sort(nums); //排序,这样重复元素会聚集在一起
        backtrack(res, nums, new ArrayList<Integer>(), visited);
        return res;
    }
    public void backtrack(List<List<Integer>> res, int[] nums, ArrayList<Integer> tmp, int[] visited) {
        if (tmp.size() == nums.length) { //递归终止条件,遍历到了数组末尾
            res.add(new ArrayList<>(tmp));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            //若当前元素与前一个元素相等,且前一元素未被访问过,就直接跳过,避免重复排列
            if (i > 0 && nums[i] == nums[i-1] && visited[i-1] == 0){
                continue;
            }
            if(visited[i] == 0){
                visited[i] = 1;
                tmp.add(nums[i]);
                //递归访问没访问过的位置
                backtrack(res, nums, tmp, visited);
                //在回溯过程中还原到上一状态
                visited[i] = 0;
                tmp.remove(tmp.size() - 1);
            }
        }
    }
}

全部评论

相关推荐

ProMonkey2024:5个oc?厉害! 但是有一个小问题:谁问你了?😡我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了(别的帖子偷来的,现学现卖😋)
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务