Table of Contents
平时工作里都是每个变量单独声明赋值的,今天刷 leetcode 的时候用了连续赋值,然后就踩坑了。
问题
题目是:109. 有序链表转换二叉搜索树。
解法:
/** 快慢指针找中点 */ var sortedListToBST = function(head) { if (!head) return head if (!head.next) { head.left = null head.right = null return head } // let fast = slow = head let fast = head let slow = head let pre = null // 找中点 while(fast && fast.next) { pre = slow slow = slow.next fast = fast.next.next } // 断开左侧 if (pre) pre.next = null slow.left = sortedListToBST(head) slow.right = sortedListToBST(slow.next) return slow }
声明赋值变量 fast 和 slow 的时候,第一次用的连续赋值,这导致解答错误。
[-10,-3,0,5,9] => [-3, -10]
换成分别声明赋值后才正确。
[-10,-3,0,5,9] => [0,-3,9,-10,null,5]
探索
连续声明赋值语句:let fast = slow = head 等于 let fast = (slow = head)。在函数 while 循环里开始和结束的位置打印出相关变量后发现,第一轮是没有问题的,问题在进入递归以后。
猜测进入递归以后的 slow 使用的是上一轮声明的 slow。
测验:
function test(end) { let a = b = { a: 1 } console.log(JSON.stringify(b)) if (end) { b = 1 return } else { test(true) } console.log(JSON.stringify(b)) } test() // {"a":1} // {"a":1} // 1
第二轮的 b 影响了第一轮里的 b,这说明猜测是对的。连续声明赋值时,引擎从右往左执行,遇到已经存在的变量会直接使用。