LeetCode第19题链表问题:移动快慢指针不修改head修改next会修改的原因
问题解答
核心底层逻辑:JS 引用类型的赋值规则
在JS中,对象类型的变量存的是指向内存中实际对象的地址,两类操作的差异本质上是「修改变量本身存储的地址」和「修改地址指向的实际对象的属性」的区别。
疑问1解答:为什么fast = fast.next不会修改head和slow?
初始化时fast = head确实是把head存储的节点地址赋值给了fast,此时fast、slow、head三个变量存的是同一个地址,指向同一个节点对象。
但fast = fast.next这个操作,是把fast.next存储的下一个节点的地址,覆盖掉fast变量本身存储的地址,本质是修改fast这个变量本身的指向,完全没有触碰任何节点对象的属性,所以不管fast怎么移动,head、slow存储的地址都不会变,指向的节点对象也不会被修改。
举个通俗的例子:你、小明、小红三个人都指着同一个路牌A,你现在转身指向下一个路牌B,完全不影响小明、小红还是指着路牌A,路牌A本身也不会有任何变化。
疑问2解答:为什么slow.next = slow.next.next会修改原head链表?
这个操作不是修改slow变量本身的指向,而是修改slow当前指向的节点对象的next属性:把这个节点原本指向第N个节点的next指针,改成指向第N+1个节点。
因为slow当前指向的节点本身就是原head链表里的节点,你修改了这个节点的属性,整个链表的结构自然就变了,head作为指向链表头的引用,自然能感知到这个变化。
对应刚才的例子:你还是指着路牌A,现在你把路牌A上写的「下一站指向B」改成「下一站指向C」,路牌A本身的内容变了,所有指着路牌A的人(包括head)看到的下一站信息都会跟着变。
相关代码回顾
var removeNthFromEnd = function(head, n) { let fast = head, slow = head for (let i = 0; i < n; i++) fast = fast.next // 仅修改fast本身的指向,不碰节点属性 if (!fast) return head.next while (fast.next) { fast = fast.next // 仅修改fast本身的指向 slow = slow.next // 仅修改slow本身的指向 } slow.next = slow.next.next // 修改slow指向的节点的next属性,修改了链表本身 return head };
内容的提问来源于stack exchange,提问作者dsjfhdjshfjkdshjf
相关产品推荐
相关产品推荐

