LeetCode题解:46. 全排列,回溯,JavaScript,详细注释

原题链接:https://leetcode-cn.com/problems/permutations/

解题思路:

可以先参考官方题解中的视频讲解。

  1. 使用DFS生成所有可能的排列情况。
  2. 需要使用used数组,标识nums中每个值是否被使用过。
  3. 清除状态的注意点:
    • 由于permutation和used变量会在每次递归被重复使用,需要注意每次递归后恢复当前状态。
    • 假设是第一层递归,for循环清除状态后每次得到的permutation分别为[1][2][3], used分别为[true, false, false][false, true, false][false, false, true]
    • 也就是说,当permutation为[2]时,上一次循环中所有可能的排列情况都已被输出,而且nums所有被使用过的状态都被清除,不会影响当前的递归。
  4. 递归终止时,由于permutation只是一个引用,即它的值会随着函数的运行不断改变,因此需要将其copy一份,否则最终输出的结果都会是[]
function recursion(nums, result, permutation, used) {
  // 1. 递归终止条件
  // 当排列的结果达到原序列长度时,退出循环
  if (permutation.length === nums.length) {
    // 将当前排列存入结果,需要将原数组copy一份,否则permutation会在for循环结束后被清空
    result.push(permutation.slice());
    return;
  }

  // 利用循环产生不同的排列
  // 假设是第一层递归,for循环每次得到的permutation分别为[1], [2], [3]。
  // 下一层的递归就在第一层的基础上继续进行
  // 由于进入每一层递归时,并不知道上一层的排列情况,只能进行遍历查找。
  for (let i = 0; i < nums.length; i++) {
    // 2. 当前层的递归逻辑
    // 如果当前值已经被使用过,则不可以进行排列,直接跳过
    if (used[i]) {
      continue;
    }
    // 当前值已经进行排列,在used中进行标识
    used[i] = true;
    // 将当前值存入排列
    permutation.push(nums[i]);

    // 3. 下探到下一层递归
    // 注意此时为深度优先遍历,也就是说recursion完成之后,已经处理完了一种排列的最终结果
    recursion(nums, result, permutation, used);

    // 4. 恢复当前层状态
    // 在当前值被使用过后,将used置为空,提供给下一次for循环使用
    used[i] = false;
    // 将当前已使用的值从permutation中弹出,避免英下乡下一次循环结果
    permutation.pop();
  }
}
/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var permute = function (nums) {
  let result = []; // 存储结果
  let permutation = []; // 存储每次排列的结果
  let used = new Array(nums.length).fill(false); // 通过index对应的布尔值,标识nums中各个值是否被使用
  // 递归生成全排列
  recursion(nums, result, permutation, used);
  return result;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
给定一个整数数组 nums 和一个目标值 target,要求在数组中找出两个数的和等于目标值,并返回这两个数的索引。 思路1:暴力法 最简单的思路是使用两层循环遍历数组的所有组合,判断两个数的和是否等于目标值。如果等于目标值,则返回这两个数的索引。 此方法的时间复杂度为O(n^2),空间复杂度为O(1)。 思路2:哈希表 为了优化时间复杂度,可以使用哈希表来存储数组中的元素和对应的索引。遍历数组,对于每个元素nums[i],我们可以通过计算target - nums[i]的值,查找哈希表中是否存在这个差值。 如果存在,则说明找到了两个数的和等于目标值,返回它们的索引。如果不存在,将当前元素nums[i]和它的索引存入哈希表中。 此方法的时间复杂度为O(n),空间复杂度为O(n)。 思路3:双指针 如果数组已经排序,可以使用双指针的方法来求解。假设数组从小到大排序,定义左指针left指向数组的第一个元素,右指针right指向数组的最后一个元素。 如果当前两个指针指向的数的和等于目标值,则返回它们的索引。如果和小于目标值,则将左指针右移一位,使得和增大;如果和大于目标值,则将右指针左移一位,使得和减小。 继续移动指针,直到找到两个数的和等于目标值或者左指针超过了右指针。 此方法的时间复杂度为O(nlogn),空间复杂度为O(1)。 以上三种方法都可以解决问题,选择合适的方法取决于具体的应用场景和要求。如果数组规模较小并且不需要考虑额外的空间使用,则暴力法是最简单的方法。如果数组较大或者需要优化时间复杂度,则哈希表或双指针方法更合适。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值