✅✅代码随想录算法训练营Day29 || 491.递增子序列 46.全排列 47.全排列 II

65 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第19天,点击查看活动详情🚀🚀

491. 递增子序列 - 力扣(LeetCode)

image.png

const findSubsequences = (nums) => {
  const res = [];
  const len = nums.length;
  const set = new Set();
  
  const dfs = (start, path) => {
    if (path.length >= 2) {
      const str = path.toString(); // path数组 转成字符串
      if (!set.has(str)) {         // set中没有存有当前path
        res.push(path.slice());    // 推入一份path的拷贝
        set.add(str);              // 存入set,记录一下
      }
    }
    for (let i = start; i < len; i++) {      // 枚举出当前所有的选项,从start到末尾
      const prev = path[path.length - 1];    // 上一个选择,即path数组的末尾元素
      const cur = nums[i];                   // 当前选择
      if (path.length == 0 || prev <= cur) { // 如果path为空,或满足递增关系,则可选择
        path.push(cur);                      // 选择当前的数字
        dfs(i + 1, path);                    // 继续往下递归,注意传的是i+1
        path.pop();                          // 撤销选择当前数字,选择别的数字
      }
    }
  };
  dfs(0, []); //递归的入口,从下标0到末尾的数组中选择合适的数加入path,组成解集。初始path是空数组
  return res;
};

难点

这题最大的难点是去重

有没有发现如果这里还是用了我们之前的去重逻辑,会对原数组进行一个排序,但排序之后又会发现我们改变了原数组,这直接把题意都改了,这样还要别人来找递增子序列??

所以这道题要寻找一个全新的去重逻辑

  • 用set去重
    const str = path.toString(); // path数组 转成字符串
      if (!set.has(str)) {         // set中没有存有当前path
        res.push(path.slice());    // 推入一份path的拷贝
        set.add(str);              // 存入set,记录一下
      }
    

    注意要放字符串~

  • path入栈

    注意条件是要符合递增才能入栈

46. 全排列 - 力扣(LeetCode)

image.png

var permute = function(nums) {
   const res = [], path = [];
   let used = []
   let len = nums.length;
   backtracking();
   return res;
   
   function backtracking() {
       if(path.length === len) {
           res.push([...path]);
           return;
       }
       for (let i = 0; i < len; i++ ) {
           if(used[i]) continue;
           path.push(nums[i]);
           used[i] = true; // 同支
           backtracking();
           path.pop();
           used[i] = false;
       }
   }
};

来到全排列了~

难点

  • dfs里没有index了,因为每次都要重新遍历一次
  • 要用used数组记录,防止重复遍历。
  • 出栈的时候也别忘了used数组

47. 全排列 II - 力扣(LeetCode)

image.png

var permuteUnique = function (nums) {
    nums.sort((a, b) => {
        return a - b
    })
    let result = []
    let path = []

    function backtracing(used) {
        if (path.length === nums.length) {
            result.push([...path])
            return
        }
        for (let i = 0; i < nums.length; i++) {
            if (nums[i] === nums[i - 1] && !used[i - 1]) {
                continue
            }
            if (!used[i]) {
                used[i] = true;
                path.push(nums[i])
                backtracing(used)
                path.pop()
                used[i] = false
            }
        }
    }
    backtracing([])
    return result
};

难点

这里在used的基础上进行了去重

  if (nums[i] === nums[i - 1] && !used[i - 1]) {
     continue
  }

核心是这句话!used[i - 1] 如果不加这句话,[1,1,2],这样直接会在第二层遍历1的时候就会出问题。