# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
res = ListNode(0)
cur = res
carry = 0
while l1 or l2:
val1 = l1.val if l1 else 0
val2 = l2.val if l2 else 0
cur.next = ListNode((val1 + val2 + carry) % 10)
carry = (val1 + val2 + carry) // 10
cur = cur.next
if l1:
l1 = l1.next
if l2:
l2 = l2.next
if carry == 1:
cur.next = ListNode(carry)
return res.next
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
# # 迭代
# pre = None
# cur = head
# while cur:
# nex = cur.next
# cur.next = pre
# pre = cur
# cur = nex
# return pre
# 递归
if not head or not head.next:
return head
newHead = self.reverseList(head.next)
head.next.next = head
head.next = None
return newHead
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
# 一次遍历,双指针
dummy = ListNode(0, head)
p = dummy
q = dummy
# q 向前移动 n+1
for i in range(n+1):
q = q.next
while q:
p = p.next
q = q.next
p.next = p.next.next
return dummy.next
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
# # 迭代
# res = ListNode(0)
# cur = res
# while list1 or list2:
# val1 = list1.val if list1 else float('inf')
# val2 = list2.val if list2 else float('inf')
# if val1 <= val2:
# cur.next = list1
# list1 = list1.next
# else:
# cur.next = list2
# list2 = list2.next
# cur = cur.next
# return res.next
# 递归
if list1 is None:
return list2
elif list2 is None:
return list1
elif list1.val < list2.val:
list1.next = self.mergeTwoLists(list1.next, list2)
return list1
else:
list2.next = self.mergeTwoLists(list1, list2.next)
return list2
优先级队列 or 分治
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
# # 迭代
# res = ListNode(0)
# cur = res
# ln = []
# invalidNum = 0
# n = len(lists)
# for i in range(n):
# ln.append(lists[i])
# if not lists[i]:
# invalidNum += 1
# def findMin(vals):
# return vals.index(min(vals))
# while invalidNum != n:
# vals = []
# for i in range(n):
# val = ln[i].val if ln[i] else float('inf')
# vals.append(val)
# print(vals)
# index = findMin(vals)
# cur.next = ln[index]
# ln[index] = ln[index].next
# if not ln[index]:
# invalidNum += 1
# cur = cur.next
# return res.next
# # 优先级队列 O(nklogk)
# import heapq
# dummy = ListNode(0)
# p = dummy
# head = []
# for i in range(len(lists)):
# if lists[i] :
# heapq.heappush(head, (lists[i].val, i))
# lists[i] = lists[i].next
# while head:
# val, idx = heapq.heappop(head)
# p.next = ListNode(val)
# p = p.next
# if lists[idx]:
# heapq.heappush(head, (lists[idx].val, idx))
# lists[idx] = lists[idx].next
# return dummy.next
# 分治 O(nklogk)
if not lists:return
n = len(lists)
return self.merge(lists, 0, n-1)
def merge(self,lists, left, right):
if left == right:
return lists[left]
mid = left + (right - left) // 2
l1 = self.merge(lists, left, mid)
l2 = self.merge(lists, mid+1, right)
return self.mergeTwoLists(l1, l2)
def mergeTwoLists(self,l1, l2):
if not l1:return l2
if not l2:return l1
if l1.val < l2.val:
l1.next = self.mergeTwoLists(l1.next, l2)
return l1
else:
l2.next = self.mergeTwoLists(l1, l2.next)
return l2
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def swapPairs(self, head: ListNode) -> ListNode:
# # 递归
# if not head or not head.next:
# return head
# nex = head.next
# head.next = self.swapPairs(nex.next)
# nex.next = head
# return nex
# 迭代
dummy = ListNode(0, head)
cur = dummy
while cur.next and cur.next.next:
node1 = cur.next
node2 = node1.next
node3 = node2.next
cur.next = node2
node2.next = node1
node1.next = node3
cur = node1
return dummy.next
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
dummy = ListNode(0, head)
pre = dummy
end = dummy
def reverse(node):
if not node or not node.next:
return node
res = reverse(node.next)
node.next.next = node
node.next = None
return res
while end and end.next:
n = k
# 终节点前进 k 步,找到翻转的最后一个节点
while n and end:
end = end.next
n -= 1
# 如果是空,说明不足 k 个,不翻转
if not end:
break
# 记录后继结点
nex = end.next
# 翻转 start-end
end.next = None
start = pre.next
pre.next = reverse(start)
# 翻转后连接后继结点
start.next = nex
# 更新 pre 和 end
end = start
pre = start
return dummy.next
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
# 将链表闭合为环,之后在指定位置断开
if not head or not head.next:
return head
# 找到最后一个节点,闭合为环
cur = head
n = 1
while cur.next:
cur = cur.next
n += 1
cur.next = head
# 从头节点开始走 k1-1 步,断开
k1 = n - k % n
print(n, k1)
cur = head
while k1 - 1:
cur = cur.next
k1 -= 1
nex = cur.next
cur.next = None
return nex
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
if not head or not head.next:
return head
dummy = ListNode(0, head)
pre = dummy
cur = head
while cur:
# 跳过当前的重复节点,使得cur指向当前重复元素的最后一个位置
while cur.next and cur.val == cur.next.val:
cur = cur.next
if pre.next == cur:
# pre和cur之间没有重复节点,pre后移
pre = pre.next
else:
# pre->next指向cur的下一个位置(相当于跳过了当前的重复元素)
# 但是pre不移动,仍然指向已经遍历的链表结尾
pre.next = cur.next
cur = cur.next
return dummy.next
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
dummy = ListNode(0, head)
pre = dummy
cur = head
while cur:
while cur.next and cur.val == cur.next.val:
cur = cur.next
pre.next = cur
cur = cur.next
pre = pre.next
return dummy.next
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def partition(self, head: ListNode, x: int) -> ListNode:
# 分割成两个链表,一个存储小于 x 节点,一个存储大于等于 x 的节点
# 遍历完成后,连接两个链表
dummySmall = ListNode(0)
dummyLarge = ListNode(0)
curSmall = dummySmall
curLarge = dummyLarge
cur = head
while cur:
if cur.val < x:
curSmall.next = cur
curSmall = curSmall.next
else:
curLarge.next = cur
curLarge = curLarge.next
cur = cur.next
curSmall.next = dummyLarge.next
curLarge.next = None
return dummySmall.next
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseBetween(self, head: ListNode, left: int, right: int) -> ListNode:
# # 两次遍历
# dummy = ListNode(0, head)
# pre = dummy
# cur = head
# revHead = None
# nex = None
# n = 1
# # left=right,无需翻转,直接返回即可
# if left == right:
# return head
# while cur:
# if n == left:
# revHead = cur
# cur = cur.next
# n += 1
# if n == right:
# nex = cur.next
# cur.next = None
# break
# if n < left:
# cur = cur.next
# pre = pre.next
# n += 1
# else:
# cur = cur.next
# n += 1
# def reverse(node):
# if not node or not node.next:
# return node
# res = reverse(node.next)
# node.next.next = node
# node.next = None
# return res
# pre.next = reverse(revHead)
# revHead.next = nex
# return dummy.next
# 一次遍历
dummy = ListNode(0, head)
pre = dummy
for _ in range(left - 1):
pre = pre.next
cur = pre.next
for _ in range(right - left):
nex = cur.next.next
cur.next.next = pre.next
pre.next = cur.next
cur.next = nex
return dummy.next
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def sortedListToBST(self, head: Optional[ListNode]) -> Optional[TreeNode]:
# 分治,找到链表中间节点,分别处理左右子树
# 获取中间节点,快慢指针
def getMid(left, right):
slow, fast = left, left
while fast != right and fast.next != right:
slow = slow.next
fast = fast.next.next
return slow
def buildTree(left, right):
if left == right:
return None
mid = getMid(left, right)
root = TreeNode(mid.val)
root.left = buildTree(left, mid)
root.right = buildTree(mid.next, right)
return root
return buildTree(head, None)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
# if not head:
# return False
# slow, fast = head, head
# while slow and fast and fast.next:
# slow = slow.next
# fast = fast.next.next
# if slow == fast:
# return True
# return False
if not head or not head.next:
return False
slow = head
fast = head.next
while slow != fast:
if not fast or not fast.next:
return False
slow = slow.next
fast = fast.next.next
return True
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
if not head:
return None
# 需要同时从 head 开始,统计快慢指针步数
slow, fast = head, head
while slow and fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
break
# 跳出循环时,f = 2s && f - s = nb
# 判断跳出循环是因为无环还是有环
if not slow or not fast or not fast.next:
return None
# 如果让指针从链表头部一直向前走并统计步数k,那么所有走到链表入口节点时的步数 是:k=a+nb(先走 a 步到入口节点,之后每绕 1 圈环( b 步)都会再次到入口节点)
# slow 固定,fast 从 head 开始,同时走 a 步会在环入口相遇
# 走到环入口需要的步数 k = a + nb
fast = head
while fast != slow:
fast = fast.next
slow = slow.next
return slow
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reorderList(self, head: ListNode) -> None:
"""
Do not return anything, modify head in-place instead.
"""
if not head or not head.next or not head.next.next:
return head
# 找中点,逆序,合并
# 快慢指针找中点
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
head1 = head
head2 = slow.next
slow.next = None
# head2 逆序
def reverse(node):
if not node or not node.next:
return node
newNode = reverse(node.next)
node.next.next = node
node.next = None
return newNode
head2New = reverse(head2)
# 合并
cur1 = head1
cur2 = head2New
while cur1 and cur2:
nex1 = cur1.next
nex2 = cur2.next
cur1.next = cur2
cur2.next = nex1
cur1 = nex1
cur2 = nex2
# # 递归
# if not head or not head.next or not head.next.next:
# return head
# # 链表长度
# size = 0
# cur = head
# while cur:
# size += 1
# cur = cur.next
# def helper(node, len):
# # 递归截止条件
# if len == 1:
# outTail = node.next
# node.next = None
# return outTail
# if len == 2:
# outTail = node.next.next
# node.next.next = None
# return outTail
# tail = helper(node.next, len-2)
# subHead = node.next
# outTail = tail.next # 这里需要返回到上一层的 tail
# node.next = tail
# tail.next = subHead
# return outTail
# helper(head, size)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def insertionSortList(self, head: ListNode) -> ListNode:
if not head or not head.next:
return head
dummy = ListNode(0, head)
cur = head
nex = cur.next
while nex:
# 如果待插入节点值大于当前节点,前进一步
if cur.val <= nex.val:
cur = cur.next
nex = cur.next
continue
# 需要插入到前面合适位置,pre 节点指向最后一个小于 待插入节点 的位置
# 待插入节点需要插入到 pre 和 pre.next 之间
pre = dummy
while pre.next.val < nex.val:
pre = pre.next
# 执行插入操作
nexnex = nex.next
prenex = pre.next
pre.next = nex
nex.next = prenex
cur.next = nexnex
nex = nexnex
return dummy.next
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
# 归并排序,找到链表中点,分割后递归调用,合并两个排序链表
# 截止条件
if not head or not head.next:
return head
# 快慢指针查找中点
# 注意 fast 需要领先 slow 一步,不然两个节点的情况会陷入死循环!!!
slow, fast = head, head.next
while fast and fast.next:
slow = slow.next
fast = fast.next.next
mid = slow.next
slow.next = None # 断开链表
# 递归调用
left, right = self.sortList(head), self.sortList(mid)
# 合并两个排序链表
res = cur = ListNode(0)
while left and right:
if left.val < right.val:
cur.next = left
left = left.next
else:
cur.next = right
right = right.next
cur = cur.next
cur.next = left if left else right
return res.next
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
# 合并两个排序链表
def merge(head1: ListNode, head2: ListNode) -> ListNode:
dummyHead = ListNode(0)
temp, temp1, temp2 = dummyHead, head1, head2
while temp1 and temp2:
if temp1.val <= temp2.val:
temp.next = temp1
temp1 = temp1.next
else:
temp.next = temp2
temp2 = temp2.next
temp = temp.next
if temp1:
temp.next = temp1
elif temp2:
temp.next = temp2
return dummyHead.next
if not head:
return head
# 链表长度 length
length = 0
node = head
while node:
length += 1
node = node.next
dummyHead = ListNode(0, head)
subLength = 1
while subLength < length:
prev, curr = dummyHead, dummyHead.next
while curr:
# 获取长度为subLength的第一个链表
head1 = curr
for i in range(1, subLength):
if curr.next:
curr = curr.next
else:
break
# 获取长度为subLength的第二个链表
head2 = curr.next
curr.next = None # 断开第一个链表
curr = head2
for i in range(1, subLength):
if curr and curr.next:
curr = curr.next
else:
break
# 获取后继节点
succ = None
if curr:
succ = curr.next
curr.next = None # 断开第二个链表
merged = merge(head1, head2) # 合并,返回新链表
prev.next = merged # 连接到前驱节点
# 更新前驱节点
while prev.next:
prev = prev.next
# 更新 curr 节点
curr = succ
# 一次归并完成后更新归并长度
subLength <<= 1
return dummyHead.next
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
# # hash 集合
# setA = set()
# cur = headA
# while cur:
# setA.add(cur)
# cur = cur.next
# cur = headB
# while cur:
# if cur in setA:
# return cur
# cur = cur.next
# return None
# 双指针
# 两个指针分别遍历两个链表,到达末尾时,从另一个节点开始继续
# 如果存在交点,会在交点处相遇
# 如果不存在交点,会在结尾相遇
if not headA or not headB:
return None
curA = headA
curB = headB
while curA != curB:
if not curA:
curA = headB
else:
curA = curA.next
if not curB:
curB = headA
else:
curB = curB.next
return curA
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
dummy = ListNode(0, head)
pre = dummy
cur = head
while cur:
if cur.val != val:
cur = cur.next
pre = pre.next
continue
pre.next = cur.next
cur = cur.next
return dummy.next
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
# # 递归
# self.pre = head
# def check(node):
# if node:
# # 递归到尾节点
# if not check(node.next):
# return False
# # 判断尾节点和头结点的值
# if node.val != self.pre.val:
# return False
# # pre 节点后移
# self.pre = self.pre.next
# return True
# return check(head)
# O(1)空间复杂度 找到链表中点,断开,反转链表,判断回文,恢复链表
if not head or not head.next:
return True
# 中点
slow, fast = head, head.next
while fast and fast.next:
slow = slow.next
fast = fast.next.next
# 断开两个链表
head1 = head
head2 = slow.next
slow.next = None
# 反转链表
def reverse(node):
if not node or not node.next:
return node
newNode = reverse(node.next)
node.next.next = node
node.next = None
return newNode
head2_rev = reverse(head2)
# 判断回文
cur1 = head1
cur2 = head2_rev
res = True
while cur1 and cur2:
if cur1.val != cur2.val:
res = False
cur1 = cur1.next
cur2 = cur2.next
# 恢复链表
slow.next = reverse(head2_rev)
return res
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def oddEvenList(self, head: Optional[ListNode]) -> Optional[ListNode]:
# 分离奇偶链表,再合并
if not head or not head.next:
return head
# 奇数节点
odd = head
#偶数节点
evenHead = even = head.next
while even and even.next:
odd.next = even.next
odd = odd.next
even.next = odd.next
even = even.next
odd.next = evenHead
return head
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def __init__(self, head: Optional[ListNode]):
self.head = head
def getRandom(self) -> int:
# 水塘抽样
node = self.head
i = 1 # 从 1 开始
res = 0
while node:
if randrange(i) == 0:
res = node.val
i += 1
node = node.next
return res
# Your Solution object will be instantiated and called as such:
# obj = Solution(head)
# param_1 = obj.getRandom()
与【两数相加】区别是顺序不一致
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
# 翻转链表,通过【两数相加】,再次翻转结果链表
# 利用栈,把两个链表都入栈,之后再相加
s1, s2 = [], []
while l1:
s1.append(l1.val)
l1 = l1.next
while l2:
s2.append(l2.val)
l2 = l2.next
ans = None
carry = 0
while s1 or s2 or carry != 0:
a = 0 if not s1 else s1.pop()
b = 0 if not s2 else s2.pop()
cur = a + b + carry
carry = cur // 10
cur %= 10
curnode = ListNode(cur)
curnode.next = ans
ans = curnode
return ans