排列组合

269 阅读1分钟

排列组合

  1. 排列(不需要控制顺序,用 set 控制不选重复的数字) [1,2,3], [3,2,1]
  2. 组合 (有顺序,通过index限制)

排列

  1. 全排列
  2. 全排列II(有重复数字) [1, 1, 2]
  • 基本结构:(各元素不同时) 使用 set 去除使用过的数字
  • 去重复排列方式
  1. 先排序
  2. (i > 0 && nums[i] == nums[i-1] && !s.contains(i-1)) continue; 比如[1, 1, 2],要去除的是横向的节点,而纵向保留,纵向的 set 是会包含该数字,而横向不包含。
    public void generator(int[] nums, List<Integer> tmp, HashSet<Integer> set, List<List<Integer>> res) {
        if (tmp.size() == nums.length) {
            res.add(new ArrayList<Integer>(tmp));
            return;
        }

        for (int i = 0; i < nums.length; i++) {
            if (set.contains(nums[i])) continue;
            tmp.add(nums[i]);
            set.add(nums[i]);
            generator(nums, tmp, set, res);
            tmp.remove(tmp.size() - 1);
            set.remove(nums[i]);
        }
    }

组合

  1. 组合(不能用用过的元素,因此要使用 sort + index 的方式)
  2. 组合总和 II
  • 基本结构:使用 sort + index 不生成相同组合
  • 重复数字去重方式 if (i > index && candidates[i] == candidates[i-1]) continue; index的核心内涵表示层数,第0层第1层第2层,而i则是从 index起开始取
    public void helper(List<List<Integer>> res, List<Integer> tmp, int[] nums, int index) {
        res.add(new ArrayList<>(tmp));

        for (int i = index; i < nums.length; i++) {
            if (i > index && nums[i] == nums[i-1]) continue;
            tmp.add(nums[i]);
            helper(res, tmp, nums, i + 1);
            tmp.remove(tmp.size() - 1);
        }
    }