链表
链表 - Day1
val 为节点值,next 为节点 listnode
创建虚拟节点 会方便删除等操作 dummy = listnode[next = head]
class ListNode: def __init__(self, val, next = None): self.val = val self.next = next ## self调用实例,例如data.min()前面的即为实例
创建装饰器(本质上是一个高阶函数,它接受一个函数作为参数,并返回一个新的函数,可以使函数每次都连带执行)
@staticmethod:将方法定义为静态方法,不需要传递 self 参数。
@classmethod:将方法定义为类方法,第一个参数是类对象 cls。
@property:将方法转换为属性,可以通过访问属性的方式调用方法。
from typing import Optional, List class ListNode: def __init__(self, val, next = None): self.val = val self.next = next # 辅助函数: 将列表转换成链表 def list_to_linkedlist(elements: List[int]) -> Optional[ListNode]: dummy_head = ListNode() current = dummy_head for element in elements: current.next = ListNode(val=element) current = current.next return dummy_head.next # 辅助函数: 将链表转换成列表 def linkedlist_to_list(head: Optional[ListNode]) -> List[int]: elements = [] current = head while current: elements.append(current.val) current = current.next return elements # 装饰器: 转换输入和输出 def convert_input_output(func): def wrapper(self, head_list: List[int], val: int) -> List[int]: head = list_to_linkedlist(head_list) # 将列表转换成链表 new_head = func(self, head, val) # 调用原函数 result_list = linkedlist_to_list(new_head) # 将结果链表转换回列表 return result_list return wrapper
203.移除链表元素
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
主要在于加虚拟节点,然后依次遍历
class Solution: @convert_input_output def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]: dummy_head = ListNode(next = head) # 创建虚拟头部节点以简化删除过程 current = dummy_head # 遍历列表并删除值为val的节点 while current.next: if current.next.val == val: current.next = current.next.next else: current = current.next return dummy_head.next
707.设计链表的五个接口
获取链表第index个节点的数值
在链表的最前面插入一个节点
在链表的最后面插入一个节点
在链表第index个节点前面插入一个节点
删除链表的第index个节点
class MyLinkedList: def __init__(self): self.dummy_head = ListNode() self.size = 0 def get(self, index: int) -> int: current = self.dummy_head if index >= 0 and index <= self.size: for i in range(index): current = current.next return current.val else: return -1 def addAtHead(self, val: int) -> None: new_head = ListNode(val, self.dummy_head.next) self.size += 1 def addAtTail(self, val: int) -> None: current = self.dummy_head while current.next: current = current.next current.next = ListNode(val) self.size += 1 def addAtIndex(self, index: int, val: int) -> None: current = self.dummy_head if index >= 0 and index <= self.size: for i in range(index-1): current = current.next new_node = ListNode(val, current.next) current.next = new_node else: return self.size += 1 def deleteAtIndex(self, index: int) -> None: current = self.dummy_head if index >= 0 and index <= self.size: for i in range(index - 1): current = current.next current.next = current.next.next else: return self.size -= 1
链表 - Day2
206.反转链表
双指针,类似数组,但要注意的是需要增加临时节点存储原链表下一节点,否则链表转向后会断开无法继续循环
class Solution: @convert_input_output def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: cur = head pre = None # 不可以用listnode(),会使得结果增加一个节点 while cur: tmp = cur.next # 存储下一节点,为了遍历节点 cur.next = pre # 反转方向 pre = cur # 更新 新链表 cur = tmp # 遍历原方向下一个节点 return pre
24.两两交换链表中的节点
需要递归,循环内交换前后两个节点,前节点向后连接时递归后面的节点
class Solution: def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]: if head is None or head.next is None: return head pre = head cur = head.next next = head.next.next cur.next = pre # 后节点连接前节点 pre.next = self.swapPairs(next) # 前节点连接后后节点,该节点需更新,递归 return cur
19.删除链表的倒数第 N 个结点
好牛逼的思路,快指针先走n+1步,剩下走的路就是慢指针需要走的路,就可以找到倒数n的节点位置
class Solution: @convert_input_output def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]: dummy = ListNode(next = head) slow = fast = dummy for i in range(n+1): fast = fast.next while fast: slow = slow.next fast = fast.next slow.next = slow.next.next return dummy.next
面试题 02.07. 链表相交
重点在于对齐,因为如果相交,后续节点长度相等,只要从短的一条链同步进行即可,从后往前判断不现实
class Solution: def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode: lenA = 0 lenB = 0 curA = headA curB = headB while curA: # 计算长度 lenA += 1 curA = curA.next while curB: lenB += 1 curB = curB.next curA = headA # 重置,并排序 curB = headB if lenA > lenB: curA, curB = curB, curA lenA, lenB = lenB, lenA for i in range(lenB - lenA): # 长度对齐 curB = curB.next while curA: if curA == curB: return curA curA = curA.next curB = curB.next return None
142.环形链表 II
快的走两步,慢的走一步,环形的话一定会相遇,相遇时重置慢指针
2(x+y) = x+n(y+z)+y
x+y = n(y+z) 原地走n圈
x = n(y+z)-y 即回到相遇点
class Solution: def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]: slow = head fast = head while fast and fast.next: slow = slow.next fast = fast.next.next if slow == fast: slow = head while slow != fast: slow = slow.next fast = fast.next return slow return None