• 力扣:包含重复元素的全排列问题


    给定一个可包含重复数字的序列,返回所有不重复的全排列

    这题与上题的全排列问题类似,问题在于如何将重复序列排除在外。
    这里就需要剪枝思想,即去掉多余的子树。
    我们先看图,令nums=[1,1,2] ![](https://img2020.cnblogs.com/blog/1809280/202004/1809280-20200430115337390-1498940799.png) 图中可以看出,[1]节点与[1]节点一致,当[1`]节点选择子节点时与[1]节点选择时一致,故应该去除。类推。
    再看如何判断剪枝:
    nums[0]=1,nums[1]=1.我们需要将nums[i-1]与nums[i]进行数值判断。同时在nums[i]为父节点进行遍历时,判断nums[i-1]是否已被调用。同时注意边界i>0;
    代码在全排列问题上添加一个剪枝语句。

    public List<List<Integer>> permute(int[] nums) {
            int numsLength = nums.length; // numsLength为nums长度
            List<List<Integer>> res = new ArrayList<>(); // 返回值
            Array.sort(nums); // 排序是剪枝的前提
            Deque<Integer> path = new ArrayDeque<>(); // path类型为Stack类型,系统推荐使用Deque。
                                                        // path用来存放每一次遍历结果
            boolean[] tOf = new boolean[numsLength]; // boolean数组对应nums中数字是否被遍历
            dfs(nums,numsLength,0,path,tOf,res);
            return res;
        }
    
        private void dfs(int[] nums, int numsLength, int depth, Deque<Integer> path, boolean[] tOf, List<List<Integer>> res) {
            // 遍历结束条件
            if (numsLength == depth) {
                res.add(new ArrayList<>(path));
                return;
            }
    
            // for循环遍历
            for (int i = 0; i < numsLength; i++) {
                // 判断nums中数字是否被遍历到
                if (tOf[i]) {
                    continue;
                }
                // 进行剪枝判断
                if (i>0 && nums[i] == nums[i -1] && !tOf[i-1]) {
                    continue;
                }
                // 若未被遍历
                path.addLast(nums[i]); // 将遍历到的nums[i]放入path尾部
                tOf[i] = true; // 将对应tof置为true,表示已遍历
                dfs(nums,numsLength,depth+1,path,tOf,res); // 继续向下搜索
                path.removeLast(); // 假设[1][2][3]回溯,返回上一层[1][2]。但是如何继续返回[1]节点呢
                                    // 这时候tof[1]为true,代表nums[1]已被遍历,继续回撤。
                tOf[i] = false;
            }
        }
    

    有错误或有其他想法的朋友们欢迎评论。

  • 相关阅读:
    关于软件工程是不是教那些不会写程序的人开发软件的一些看法。
    学习这门课的一些问题
    软件测试的平台
    课程上不明白的问题
    目前流行的源程序版本管理软件和项目管理软件都有哪些, 各有什么优缺点?
    自我介绍
    【软件工程】提问回顾与个人总结
    Google Kick Start 2019 C轮 第一题 Wiggle Walk 题解
    elasticsearch-py 解决 too_long_frame_exception 问题
    Redis集群学习笔记
  • 原文地址:https://www.cnblogs.com/njuptzheng/p/12807714.html
Copyright © 2020-2023  润新知