class Solution: def deleteDuplicates(self, head: ListNode) -> ListNode: cur = head while cur and cur.next: if cur.val == cur.next.val: cur.next = cur.next.next else: cur = cur.next return head
class Solution: def deleteDuplicates(self, head: ListNode) -> ListNode: if not head or not head.next: # 空链表或单个节点链表 return head dummy = ListNode(0) # 定义哑节点 dummy.next = head pre = dummy # 哑节点指针 cur = head # 链表指针 flag = False # 标记是否重复 while cur: while cur.next and pre.next.val == cur.next.val: cur = cur.next # 标记所有重复节点True flag = True if flag is True: # 跳过重复节点 pre.next = cur.next flag = False else: pre = cur # 下一个节点不重复 cur = cur.next return dummy.next
# 迭代 class Solution: def reverseList(self, head: ListNode) -> ListNode: pre = None cur = head while cur: temp = cur.next # 下一个存储节点 cur.next = pre # 指向前驱节点 pre = cur cur = temp # cur指向原来的下一个 return pre
# 递归 class Solution: def reverseList(self, head: ListNode) -> ListNode: if not head or not head.next: return head p = self.reverseList(head.next) head.next.next = head head.next = None return p
class Solution:
def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
dummy = ListNode(None)
dummy.next = head
pre = dummy
for i in range(1, m):
pre = pre.next # 前驱指针移动到位置m
cur = pre.next
for i in range(m, n): # 两两交换节点
temp = cur.next
cur.next = temp.next # cur一直不变,只修改指针到下一个位置
temp.next = pre.next # temp.next指向pre的next,也就是最新的第m个位置
pre.next = temp # 更新temp为最新的第m个位置
return pre
21. 合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
思路:建立新链表,依次按升序链接两个链表的元素
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
dummy = ListNode(None)
pre = dummy
while l1 and l2:
if l1.val < l2.val:
pre.next = l1
l1 = l1.next
else:
pre.next = l2
l2 = l2.next
pre = pre.next
pre.next = l1 if l1 else l2
return dummy.next
86. 分隔链表
给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。
思路:创建双链表,一个存储小于x的值,一个存储大于x的值
class Solution:
def partition(self, head: ListNode, x: int) -> ListNode:
before = befornHead = ListNode(None)
after = afterHead = ListNode(None)
while head:
if head.val < x:
before.next = head
before = before.next
else:
after.next = head
after = after.next
head = head.next
after.next = None
before.next = afterHead.next
return befornHead.next
148. 排序链表
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
思路:归并排序,找中点和合并操作
# 归并排序(递归),空间复杂度O(n)
class Solution:
def sortList(self, head: ListNode) -> ListNode:
if not head or not head.next:
return head
slow, fast = head, head.next
while fast and fast.next:
slow, fast = slow.next, fast.next.next
mid = slow.next
slow.next = None
left = self.sortList(head)
right = self.sortList(mid)
h = res = ListNode(0)
while left and right:
if left.val < right.val:
h.next, left = left, left.next
else:
h.next, right = right, right.next
h = h.next
h.next = left if left else right
return res.next
# 快速排序
class Solution:
def sortList(self, head: ListNode) -> ListNode:
if head is None:
return head
# 分成三个链表,分别是比轴心数小,相等,大的数组成的链表
big = None
small = None
equal = None
cur = head
while cur:
temp = cur
cur = cur.next
if temp.val < head.val:
temp.next = small
small = temp
elif temp.val > head.val:
temp.next = big
big = temp
else:
temp.next = equal
equal = temp
# 拆完各自排序即可,equal 无需排序
big = self.sortList(big)
small = self.sortList(small)
ret = ListNode(None)
cur = ret
# 将三个链表组合成一起
# 可以同时返回链表的头指针和尾指针加速链表的合并。
for p in [small, equal, big]:
while p is not None:
cur.next = p
p = p.next
cur = cur.next
cur.next = None
return ret.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:
return head
slow, fast = head, head
# 找到链表中点
while fast.next and fast.next.next:
slow = slow.next
fast = fast.next.next
# 反转后半部分
print(slow.next)
right = None
cur = slow.next
while cur:
temp = cur.next
cur.next = right
right = cur
cur = temp
# 将反转的后半部分插入到前半部分
left = head
while left and right:
slow.next = right.next
right.next = left.next
left.next = right
left = right.next
right = slow.next
141. 环形链表
给定一个链表,判断链表中是否有环。
思路1:哈希表,统计每个元素出现的次数
思路2:快慢指针,快慢指针相同则有环,证明:如果有环每走一步快慢指针距离会减 1
# 哈希表
class Solution:
def hasCycle(self, head: ListNode) -> bool:
dic = {}
while head:
if head in dic:
return True
else:
dic[head] = 1
head = head.next
return False
# 快慢指针
class Solution:
def hasCycle(self, head: ListNode) -> bool:
if head is None or head.next is None:
return False
slow = head
fast = slow.next
while fast and fast.next:
fast = fast.next.next
slow = slow.next
if fast == slow:
return True
return False
142. 环形链表 II
给定一个链表,返回链表开始入环的第一个节点。如果链表无环,则返回 null。
思路:快慢指针,快慢相遇之后,慢指针回到头,快慢指针步调一致一起移动,相遇点即为入环点
class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
fast, slow = head, head
while True:
if not (fast and fast.next):
return
slow = slow.next
fast = fast.next.next
if slow == fast:
break
fast = head
while fast != slow:
fast = fast.next
slow = slow.next
return fast
138. 复制带随机指针的链表
给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。
要求返回这个链表的 深拷贝。
思路:1、hash 表存储指针,2、复制节点跟在原节点后面
class Solution:
def copyRandomList(self, head: 'Node') -> 'Node':
if not head:
return
dic = {}
dic[None] = None
cur = head
while cur:
if cur not in dic:
dic[cur] = Node(cur.val) # 将当前未拷贝的节点放入字典中
if cur.random not in dic:
dic[cur.random] = Node(cur.random.val) # 将当前未拷贝的random指针放入字典中
dic[cur].random = dic[cur.random]
if cur.next not in dic:
dic[cur.next] = Node(cur.next.val) # 将当前未拷贝的next指针放入字典中
dic[cur].next = dic[cur.next]
cur = cur.next
return dic[head]
# 将值复制到数组中
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
visit = []
cur = head
while cur:
visit.append(cur.val)
cur = cur.next
return visit == visit[::-1]
# 找中点 -> 反转 -> 比较
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
pre = None
slow, fast = head, head
while fast and fast.next:
slow = slow.next # 使慢指针指向中间节点
fast = fast.next.next
while slow: # 反转后半部分,pre指向反转部分
temp = slow.next
slow.next = pre
pre = slow
slow = temp
while head and pre: # 比较两部分是否相同
if head.val != pre.val:
return False
head = head.next
pre = pre.next
return True