Python中LinkedList两两节点交换时无法修改节点引用的问题
嘿,我太懂这种调试链表交换时卡壳的感觉了!两两交换相邻节点看着简单,但指针引用的坑真的容易踩,尤其是第一次循环就出问题,大概率是节点引用的指向没处理全,或者没考虑头节点的特殊情况。下面我帮你拆解常见问题和解决办法:
1. 头节点的变更没处理
如果你的代码直接从原头节点开始交换,第一次交换后新的头节点应该是原来的第二个节点,但如果没更新链表的head引用,后续遍历还是从旧头节点走,就会出现“交换无效”的假象。比如原链表是1->2->3->4,第一次交换后实际是2->1->3->4,但如果head还指向1,输出时就会从1开始,看起来根本没交换。
2. 指针引用只改了一半
两两交换需要修改三个节点的引用关系:当前节点(curr)、下一个节点(next),还有curr的前一个节点(prev)的next指向。很多人只改了curr和next的互相指向,忘了把prev的next更新成新的当前节点(也就是原来的next),导致链表断链或者旧节点还挂在链上。比如错误的写法可能是:
// 只改了curr和next的指向,漏掉了prev的更新 curr.next = next.next; next.next = curr;
3. 循环条件写错
如果循环条件设成curr != null而不是curr != null && curr.next != null,当链表长度为奇数时,最后一个节点会被错误处理,甚至触发空指针异常。如果你的链表刚好只有1个节点,第一次循环就会直接跳过或者报错,看起来交换没效果。
最稳妥的方式是用一个虚拟头节点(dummy head),这样不用单独处理头节点的特殊情况,所有交换逻辑完全统一。步骤如下:
- 创建一个虚拟节点,让它的
next指向原链表的head - 用一个
prev指针指向虚拟节点,作为当前交换对的前一个节点 - 循环条件设为
prev.next != null && prev.next.next != null(确保有两个节点可以交换) - 每次循环中按顺序修改指针:
- 标记要交换的两个节点:
curr = prev.next,nextNode = curr.next - 把curr指向next的下一个节点:
curr.next = nextNode.next - 把next指向curr:
nextNode.next = curr - 把prev的next指向新的交换头(nextNode):
prev.next = nextNode - 把prev移动到curr,准备下一组交换
- 标记要交换的两个节点:
- 最后把链表的
head更新为dummy.next
示例代码(假设你的Node类有val和next属性)
public ListNode swapPairs(ListNode head) { // 创建虚拟头节点,避免单独处理头节点 ListNode dummy = new ListNode(0); dummy.next = head; ListNode prev = dummy; // 确保有两个节点可以交换 while (prev.next != null && prev.next.next != null) { ListNode curr = prev.next; ListNode nextNode = curr.next; // 执行交换操作 curr.next = nextNode.next; nextNode.next = curr; prev.next = nextNode; // 移动prev到下一组交换的前一个节点 prev = curr; } // 返回新的头节点 return dummy.next; }
你可以对照上面的逻辑检查自己的代码:
- 是不是没更新头节点?比如第一次交换后
head还是指向原来的第一个节点? - 是不是漏掉了
prev.next = nextNode这关键一步? - 循环条件是不是没判断
curr.next != null?
比如如果你的原代码没有用虚拟节点,第一次交换后必须手动把head更新为原来的第二个节点,否则后续遍历还是从旧head开始,自然看不到交换效果。
内容的提问来源于stack exchange,提问作者NPE_Exception

