记一次数组交换位置时遇到的坑

在练习leetcode第41题的时候,中间有一个原地交换元素的步骤,很简单的一个步骤却被硬控一整天,记录一下硬控我的两个大坑。

  • 大牛标准答案

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    var firstMissingPositive = function(nums) {
    const n = nums.length;
    for (let i = 0; i < n; i++) {
    // 如果当前学生的学号在 [1,n] 中,但(真身)没有坐在正确的座位上
    while (1 <= nums[i] && nums[i] <= n && nums[i] !== nums[nums[i] - 1]) {
    // 那么就交换 nums[i] 和 nums[j],其中 j 是 i 的学号
    const j = nums[i] - 1; // 减一是因为数组下标从 0 开始
    [nums[i], nums[j]] = [nums[j], nums[i]];
    }
    }

    // 找第一个学号与座位编号不匹配的学生
    for (let i = 0; i < n; i++) {
    if (nums[i] !== i + 1) {
    return i + 1;
    }
    }

    // 所有学生都坐在正确的座位上
    return n + 1;
    };

    作者:灵茶山艾府
    链接:https://leetcode.cn/problems/first-missing-positive/solutions/3655377/huan-zuo-wei-tong-guo-li-zi-li-jie-suan-qa94e/
    来源:力扣(LeetCode
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 坑点一

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    var firstMissingPositive = function(nums) {
    const n = nums.length;
    for (let i = 0; i < n; i++) {
    while (1 <= nums[i] && nums[i] <= n && nums[i] !== nums[nums[i] - 1]) {
    [nums[i], nums[nums[i] - 1]] = [nums[nums[i] - 1], nums[i]];
    }
    }

    for (let i = 0; i < n; i++) {
    if (nums[i] !== i + 1) {
    return i + 1;
    }
    }

    return n + 1;
    };
    • 后果
      陷入死循环
    • 区别
      没有提取nums[i]-1,直接交换nums[i]nums[nums[i] - 1]
    • 原因
      按照代码执行顺序,表达式[nums[i], nums[nums[i] - 1]] = [nums[nums[i] - 1], nums[i]]会先计算等号右侧[nums[nums[i] - 1], nums[i]],然后计算等号左侧[nums[i], nums[nums[i] - 1]],先给nums[i]赋值,再给nums[nums[i] - 1]赋值。问题就在于给nums[nums[i] - 1]赋值之前,nums[i]已经完成赋值操作,所以此时再取值的时候就会脱离控制,造成意料之外的后果。
  • 坑点二

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    var firstMissingPositive = function(nums) {
    const n = nums.length;
    for (let i = 0; i < n; i++) {
    while (1 <= nums[i] && nums[i] <= n && nums[i] !== nums[nums[i] - 1]) {
    const j = nums[i] - 1;
    console.log(i, j)
    [nums[i], nums[j]] = [nums[j], nums[i]];
    }
    }

    for (let i = 0; i < n; i++) {
    if (nums[i] !== i + 1) {
    return i + 1;
    }
    }

    return n + 1;
    };
    • 后果
      报错Cannot set properties of undefined
    • 区别
      添加了打印语句console.log(i, j)
    • 原因
      打印语句后没有加;,导致执行的时候这行和下一行拼接在了一起,console.log(i,j)[nums[i], nums[j]] = [nums[j], nums[i]],而console方法返回undefined,相当于undefined[nums[i]] = [nums[j], nums[i]],导致了报错。

重点

当一行代码以(或者[开头点时候,最好在行首补一个;避免一些语法解析错误