LeetCode题解中Python Solution类里self关键字的用法解析
关于LeetCode 1721题题解中
pre = self的疑惑解答 核心本质:用Solution实例当虚拟头节点
题解里的pre = self是个取巧的写法,把当前Solution类的实例当成了链表的虚拟头节点,和我们平时写链表题时用dummy = ListNode(0)的作用完全一致,只是利用了Python动态语言的特性省掉了创建额外ListNode的步骤。
逐行解释关键代码
pre, pre.next = self, head- self是当前
Solution类的实例,Python允许给对象动态添加属性,所以这里直接给self新增了一个next属性,让它指向传入的链表头节点head。 - 此时
pre变量指向self这个实例,相当于pre是一个"伪链表节点",它的next指针连接着真实的链表开头,用来处理头节点交换的边界情况。
- self是当前
循环内的交换逻辑
这部分和常规的两两交换逻辑完全一致:- 每次取pre后面的两个节点
a和b - 通过三次赋值完成交换:让pre的next指向b,b的next指向a,a的next指向原来b的next
- 最后把pre移动到a,作为下一组交换的前置节点
- 每次取pre后面的两个节点
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
相关产品推荐
相关产品推荐

