You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LeetCode题解中Python Solution类里self关键字的用法解析

关于LeetCode 1721题题解中pre = self的疑惑解答

核心本质:用Solution实例当虚拟头节点

题解里的pre = self是个取巧的写法,把当前Solution类的实例当成了链表的虚拟头节点,和我们平时写链表题时用dummy = ListNode(0)的作用完全一致,只是利用了Python动态语言的特性省掉了创建额外ListNode的步骤。

逐行解释关键代码

  1. pre, pre.next = self, head

    • self是当前Solution类的实例,Python允许给对象动态添加属性,所以这里直接给self新增了一个next属性,让它指向传入的链表头节点head。
    • 此时pre变量指向self这个实例,相当于pre是一个"伪链表节点",它的next指针连接着真实的链表开头,用来处理头节点交换的边界情况。
  2. 循环内的交换逻辑
    这部分和常规的两两交换逻辑完全一致:

    • 每次取pre后面的两个节点a和b
    • 通过三次赋值完成交换:让pre的next指向b,b的next指向a,a的next指向原来b的next
    • 最后把pre移动到a,作为下一组交换的前置节点
  3. return self.next
    整个交换完成后,self的next属性已经指向了交换后的新链表的头节点(比如原链表是[A,B,C,...],第一次交换后self.next就变成了B),所以返回它就是最终的结果链表。

和常规写法的对比

常规的虚拟节点写法会是这样:

class Solution(object):
    def swapPairs(self, head):
        dummy = ListNode(0)
        dummy.next = head
        pre = dummy
        while pre.next and pre.next.next:
            a = pre.next
            b = a.next
            pre.next, b.next, a.next = b, a, b.next
            pre = a
        return dummy.next

题解里的写法只是把dummy换成了self,本质没有区别——都是用一个前置节点来处理头节点交换的边界问题,只是题解利用Python动态添加属性的特性,没有额外创建ListNode对象。

对你疑问的补充

你提到“我们不是应该只操作链表吗?”——其实这里并没有偏离链表操作,只是借了Solution实例的“壳”,给它加了个next属性当作虚拟头节点,所有的核心逻辑还是在操作原链表的节点指针,只是少创建了一个ListNode实例而已。

内容的提问来源于stack exchange,提问作者Hubert Co

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 20:03:28