JavaScript while循环有无大括号的差异及嵌套疑问(LeetCode234)
关于LeetCode 234「回文链表」代码中while循环大括号的疑问
我在解决LeetCode 234「回文链表」问题时,遇到一段超出当前水平的解决方案:
var isPalindrome = function(head) { let slow = head, fast = head, prev, temp while (fast && fast.next) slow = slow.next, fast = fast.next.next prev = slow, slow = slow.next, prev.next = null while (slow) temp = slow.next, slow.next = prev, prev = slow, slow = temp fast = head, slow = prev while (slow) { if (fast.val !== slow.val) return false else fast = fast.next, slow = slow.next } //我添加了这些大括号,代码仍能正常运行 return true };
我对代码中省略大括号的写法感到困惑,于是尝试添加大括号测试循环嵌套,但出现各种问题:
- 为第一个while循环添加大括号后,部分测试用例失败
- 为第二个while循环添加大括号后,代码超时
- 将第三个while循环嵌套在第二个循环中,代码仍无法正常运行
修改后的错误代码如下:
var isPalindrome = function(head) { let slow = head, fast = head, prev, temp while (fast && fast.next) { slow = slow.next, fast = fast.next.next prev = slow, slow = slow.next, prev.next = null } while (slow) { temp = slow.next, slow.next = prev, prev = slow, slow = temp fast = head, slow = prev; } while (slow) { if (fast.val !== slow.val) return false else fast = fast.next, slow = slow.next } return true };
嵌套第三个循环的错误代码:
var isPalindrome = function(head) { let slow = head, fast = head, prev, temp while (fast && fast.next) { slow = slow.next, fast = fast.next.next prev = slow, slow = slow.next, prev.next = null } while (slow) { temp = slow.next, slow.next = prev, prev = slow, slow = temp fast = head, slow = prev; while (slow) { if (fast.val !== slow.val) return false else fast = fast.next, slow = slow.next } } return true };
我尝试了所有嵌套组合都未成功,甚至不知道该搜索什么来理解问题。我到底忽略了什么?同时我想知道:为什么JavaScript会区分有无大括号的while循环?无大括号的while循环能否嵌套?
问题解析与解答
1. 你忽略的核心点
你没搞清楚不带大括号的while循环的执行范围,以及原代码中逗号运算符的作用:
- 不带大括号的while循环,只会执行紧跟在循环条件后的单个语句(包括用逗号连接多个表达式组成的复合语句)
- 原代码中
slow = slow.next, fast = fast.next.next是一个用逗号连接的复合语句,属于第一个while的循环体;而后面的prev = slow, slow = slow.next, prev.next = null是循环结束后才执行的代码,不属于循环体。 - 你修改时错误地把循环外的代码放进了大括号,完全改变了原算法的执行逻辑:
- 第一个while加大括号后,
prev = slow...会在每次循环迭代时执行,而原逻辑是找到链表中点后才执行一次,导致链表提前断开,测试用例失败。 - 第二个while加大括号后,
fast = head, slow = prev会在每次反转节点时执行,不断重置指针,导致循环永远无法结束,触发超时。 - 嵌套第三个循环到第二个循环里,变成每次反转一个节点就对比一次,完全不符合“反转后半段后再整体对比”的算法逻辑。
- 第一个while加大括号后,
2. JavaScript区分有无大括号的原因
大括号的作用是明确标记循环体的范围:
- 不带大括号时,循环体只能是单个语句(不管这个语句是单行赋值,还是用逗号连接的复合语句)
- 带大括号时,循环体是大括号内的所有语句,和换行无关
3. 无大括号的while循环能否嵌套
可以嵌套,但要保证每个循环的执行体是单个语句。比如:
let i = 0; while (i < 3) while (i < 2) console.log(i++);
这段代码是合法的,内层while是外层while的执行体(单个语句),会正常执行。
原代码的正确加括号版本
要保持原逻辑,加括号时需要把循环体限制为原本的复合语句,循环外的代码留在大括号外:
var isPalindrome = function(head) { let slow = head, fast = head, prev, temp; while (fast && fast.next) { slow = slow.next, fast = fast.next.next; } prev = slow, slow = slow.next, prev.next = null; while (slow) { temp = slow.next, slow.next = prev, prev = slow, slow = temp; } fast = head, slow = prev; while (slow) { if (fast.val !== slow.val) return false; else fast = fast.next, slow = slow.next; } return true; };
内容的提问来源于stack exchange,提问作者eatthischair
相关产品推荐
相关产品推荐

