目录
- class ListNode:
- def __init__(self, val=0, next=None):
- self.val = val
- self.next = next
- class Solution:
- def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
- res = None
- cur = head
- while cur:
- curNext = cur.next
- cur.next = res
- res = cur
- cur = curNext
- return res
链表内指定区间反转_牛客题霸_牛客网 (nowcoder.com)
- class Solution:
- def reverseBetween(self , head: ListNode, m: int, n: int) -> ListNode:
- # [1] 哨兵节点
- dummyNode = ListNode(-1)
- dummyNode.next = head
-
- # [2] pre指向反转区间的前一个节点
- pre = dummyNode
- for _ in range(m-1):
- pre = pre.next
-
- # [3] cur指向反转区间的第一个节点,开始反转
- cur = pre.next
- for _ in range(n-m):
- curNext = cur.next
- cur.next = curNext.next
- curNext.next = pre.next
- pre.next = curNext
- return dummyNode.next
链表中的节点每k个一组翻转_牛客题霸_牛客网 (nowcoder.com)
递归实现
- class Solution:
- def reverseKGroup(self , head: ListNode, k: int) -> ListNode:
- # [1] 找到当前要翻转的尾部
- tail = head
- for _ in range(k):
- # 如果走到链表尾则直接返回结果head
- if tail == None:
- return head
- tail = tail.next
- # [2] 翻转(在到达当前尾节点tail时)
- newHead = None
- cur = head
- while cur != tail:
- curNext = cur.next
- cur.next = newHead
- newHead = cur
- cur = curNext
- # [3] 当前尾指向下一段要翻转的链表
- head.next = self.reverseKGroup(tail, k)
- return newHead
链表相加(二)_牛客题霸_牛客网 (nowcoder.com)
- class Solution:
- # 反转链表
- def reverse(self, head: ListNode) -> ListNode:
- res = None
- cur = head
- while cur:
- curNext = cur.next
- cur.next = res
- res = cur
- cur = curNext
- return res
- def addInList(self , head1: ListNode, head2: ListNode) -> ListNode:
- if head1 is None: return head2
- if head2 is None: return head1
- # 反转链表
- head1 = self.reverse(head1)
- head2 = self.reverse(head2)
- # 创建头节点
- head = ListNode(-1)
- cur = head
- # 记录进位数
- count = 0
- while head1 is not None or head2 is not None:
- val = count
- if head1 is not None:
- val += head1.val
- head1 = head1.next
- if head2 is not None:
- val += head2.val
- head2 = head2.next
- count = val//10
- cur.next = ListNode(val%10)
- cur = cur.next
- # 判断最终是否需要进位
- if count>0:
- cur.next = ListNode(count)
- return self.reverse(head.next)
- class Solution:
- def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
- fast, slow = head, head
- while fast and fast.next:
- fast = fast.next.next
- slow = slow.next
- return slow
链表中倒数最后k个结点_牛客题霸_牛客网 (nowcoder.com)
- class Solution:
- def FindKthToTail(self , pHead: ListNode, k: int) -> ListNode:
- fast, slow = pHead, pHead
- for _ in range(k):
- if not fast:
- return None
- fast = fast.next
- while fast:
- slow = slow.next
- fast = fast.next
- return slow
删除链表的倒数第n个节点_牛客题霸_牛客网 (nowcoder.com)
- class Solution:
- def removeNthFromEnd(self , head: ListNode, n: int) -> ListNode:
- if head is None: return None
- slow, fast = head, head
- for _ in range(n):
- fast = fast.next
- # 如果n大于链表的长度,则删除链表的第一个节点(返回head.next)
- if fast is None:
- return head.next
- while fast.next:
- slow = slow.next
- fast = fast.next
- slow.next = slow.next.next
- return head
快慢指针找到中间结点,然后反转链表,最后判断是否一致
- class Solution:
- def isPalindrome(self, head: Optional[ListNode]) -> bool:
- if head is None: return True
- fast = slow = head
- # [1] slow 找到中间结点
- while fast.next and fast.next.next:
- fast = fast.next.next
- slow = slow.next
-
- # [2] 反转后半段,以newHead为头结点
- newHead = None
- cur = slow.next
- slow.next = None
- while cur:
- curNext = cur.next
- cur.next = newHead
- newHead = cur
- cur = curNext
-
- # [3] 判断
- while newHead:
- if head.val != newHead.val:
- return False
- head = head.next
- newHead = newHead.next
- return True
利用Python特性实现:存入数组直接逆置判断
- class Solution:
- def isPalindrome(self, head: Optional[ListNode]) -> bool:
- val = []
- while head:
- val.append(head.val)
- head = head.next
- return val == val[::-1]
- class Solution:
- def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
- newHead = ListNode(-1)
- cur = newHead
- while list1 and list2:
- if list1.val <= list2.val:
- cur.next = list1
- list1 = list1.next
- else:
- cur.next = list2
- list2 = list2.next
- cur = cur.next
- if list1:
- cur.next = list1
- else:
- cur.next = list2
- return newHead.next
合并k个已排序的链表_牛客题霸_牛客网 (nowcoder.com)
思路1:归并+分治
- class Solution:
- # 合并两个有序链表
- def mergeTwoLists(self, list1: ListNode, list2: ListNode) -> ListNode:
- newHead = ListNode(-1)
- cur = newHead
- while list1 and list2:
- if list1.val <= list2.val:
- cur.next = list1
- list1 = list1.next
- else:
- cur.next = list2
- list2 = list2.next
- cur = cur.next
- if list1:
- cur.next = list1
- else:
- cur.next = list2
- return newHead.next
-
- # 合并k个已排序的链表
- def mergeKLists(self, lists: List[ListNode]) -> ListNode:
- return self.divideMerge(lists, 0, len(lists) - 1)
-
- # 划分合并区间
- def divideMerge(self, lists: List[ListNode], left: int, right: int) -> ListNode:
- if left > right:
- return None
- elif left == right:
- return lists[left]
- # 从中间分成两段,再将合并好的两段合并
- mid = (left + right) // 2
- return self.mergeTwoLists(
- self.divideMerge(lists, left, mid), self.divideMerge(lists, mid + 1, right))
思路2:优先队列(堆)
- from queue import PriorityQueue
- class Solution:
- def mergeKLists(self , lists: List[ListNode]) -> ListNode:
- # 小根堆
- pg = PriorityQueue()
- # 遍历所有链表第一个元素,不为空则加入小根堆pg
- for i in range(len(lists)):
- if lists[i] is not None:
- pg.put((lists[i].val, i))
- lists[i] = lists[i].next
- # 结果链表
- res = ListNode(-1)
- cur = res
- # 直到小根堆为空
- while not pg.empty():
- # 取出最小元素
- val,idex = pg.get()
- cur.next = ListNode(val)
- cur = cur.next
- # 添加该链表的下一个元素
- if lists[idex] is not None:
- pg.put((lists[idex].val, idex))
- lists[idex] = lists[idex].next
- return res.next
160. 相交链表 - 力扣(LeetCode)两个链表的第一个公共结点_牛客题霸_牛客网 (nowcoder.com)
a,b分别为两个链表的指针,a走完head1走head2,b走完head2走head1,a和b相遇时即相交。
- class Solution:
- def FindFirstCommonNode(self , pHead1 , pHead2 ):
- a , b = pHead1, pHead2
- while a != b:
- # a从pHead1走完,再走pHead2
- if a is not None: a = a.next
- else: a = pHead2
- # b从pHead2走完,再走pHead1
- if b is not None: b = b.next
- else: b = pHead1
- return a
- #——————————————简便写法——————————————
- class Solution:
- def FindFirstCommonNode(self , pHead1 , pHead2 ):
- a, b = pHead1, pHead2
- while a != b:
- # a从pHead1走完,再走pHead2
- a = a.next if a else pHead2
- # b从pHead2走完,再走pHead1
- b = b.next if b else pHead1
- # 相遇时即为公共结点
- return a
快慢指针判断
- class Solution:
- def hasCycle(self, head: Optional[ListNode]) -> bool:
- if head is None or head.next is None: return False
- fast = slow = head
- while fast and fast.next:
- fast = fast.next.next
- slow = slow.next
- # 注意先走完再判断!
- if fast == slow:
- return True
- return False
用 set() 集合存储所有可能性
- class Solution:
- def hasCycle(self, head: Optional[ListNode]) -> bool:
- seen = set()
- while head:
- if head in seen:
- return True
- seen.add(head)
- head = head.next
- return False
快慢指针第一次相遇时停下来。快指针回到head,与慢指针一起走,再次相遇即为环入口。
- class Solution:
- def EntryNodeOfLoop(self, pHead):
- if pHead is None: return None
- fast, slow = pHead, pHead
- while fast and fast.next:
- fast = fast.next.next
- slow = slow.next
- # 停在快慢指针相遇的位置
- if slow == fast: break
- # 如果为 None 则表示不存在环
- if fast is None or fast.next is None: return None
-
- # 快指针指向 原head
- fast = pHead
- # 快慢指针同步走,再次相遇时结点为入口结点
- while fast != slow:
- fast = fast.next
- slow = slow.next
- return fast
set()集合得到入口
- class Solution:
- def EntryNodeOfLoop(self, pHead):
- ss =set()
- while pHead:
- if pHead not in ss:
- ss.add(pHead)
- pHead = pHead.next
- else:
- return pHead
- return None
单链表的排序_牛客题霸_牛客网 (nowcoder.com)
存入数组进行排序
- class Solution:
- def sortInList(self , head: ListNode) -> ListNode:
- # 存入数组
- tmp = []
- while head:
- tmp.append(head.val)
- head = head.next
- # 数组排序
- tmp.sort()
- # 构建结果链表
- res = ListNode(-1)
- cur = res
- for i in tmp:
- cur.next = ListNode(i)
- cur = cur.next
- return res.next
归并排序(递归)
- class Solution:
- # 合并两个有序链表
- def merge(self, head1: ListNode, head2: ListNode) -> ListNode:
- if head1 is None: return head2
- if head2 is None: return head1
- res = ListNode(-1)
- cur = res
- while head1 and head2:
- if head1.val <= head2.val:
- cur.next = head1
- head1 = head1.next
- else:
- cur.next = head2
- head2 = head2.next
- cur = cur.next
- cur.next = head1 if head1 else head2
- return res.next
-
- def sortInList(self , head: ListNode) -> ListNode:
- if head is None or head.next is None: return head
- premid = head
- mid = head.next
- fast = head.next.next
- # 快边指针到达末尾时,中间指针为链表的中间
- while fast and fast.next:
- premid = premid.next
- mid = mid.next
- fast = fast.next.next
- # 左边链表从中间断开
- premid.next = None
- return self.merge(self.sortInList(head), self.sortInList(mid))
链表的奇偶重排_牛客题霸_牛客网 (nowcoder.com)
- class Solution:
- def oddEvenList(self , head: ListNode) -> ListNode:
- if head is None or head.next is None: return head
- odd = head
- even = head.next
- evenHead = even
- while even and even.next:
- # odd连接偶数位的下一个
- odd.next = even.next
- odd = odd.next
- # even连接奇数位的下一个
- even.next = odd.next
- even = even.next
- odd.next = evenHead
- return head
删除有序链表中重复的元素-I_牛客题霸_牛客网 (nowcoder.com)
- class Solution:
- def deleteDuplicates(self , head: ListNode) -> ListNode:
- if head is None or head.next is None: return head
- cur = head
- while cur and cur.next:
- if cur.val == cur.next.val:
- cur.next = cur.next.next
- else:
- cur = cur.next
- return head
删除有序链表中重复的元素-II_牛客题霸_牛客网 (nowcoder.com)
- class Solution:
- def deleteDuplicates(self , head: ListNode) -> ListNode:
- if head is None or head.next is None: return head
- res = ListNode(-1)
- res.next = head
- cur = res
- while cur.next and cur.next.next:
- if cur.next.val == cur.next.next.val:
- tmp = cur.next.val
- # 将所有相同的都跳过
- while cur.next is not None and cur.next.val == tmp:
- cur.next = cur.next.next
- else:
- cur = cur.next
- return res.next