文章目录
1. 剑指Offer-24 实现链表反转 (206)
题目可以看-原题地址
- 三个指针翻转
思路:
(1):设置3指针,pre,cur和next_node
(2):实现局部反转,cur.next = pre
(3):然后对指针进行跟新,让3个指针向前移动一位
(4):特殊情况:当没有节点是要进行判断。当进行next_node更新时候也要进行判断,若cur = None 时 next_node = cur.next 则会报错。
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
if head == None:
return head
cur = head
pre = None
next_node = cur.next
while cur:
cur.next = pre
pre = cur
cur = next_node
if cur:
next_node = cur.next
head = pre
return head
- 递归
def reverseList(self, head):
if not head:
return None
if not head.next:
self._head = head
return head
headNode = self.reverseList(head.next)
head.next.next = head
head.next = None
return headNode
2. 反转链表ii (92)
题目可以看-原题地址
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
思路:
(1)可以想象两边变为三部分,前一部分,反转部分,后一部分,反转m到n之间的链表
(2)将反转好的链表与前后两部分进行拼接,设置两个站点,方便拼接
(3)当没有前一部分,即m=1时,pre1 = None那么此是头节点直接等于pre
class Solution:
def reverseBetween(self, head, m, n):
cur = head
pre = None
next_node = cur.next
for i in range(m - 1):
pre = cur
cur = next_node
if cur:
next_node = cur.next
cur1 = cur
pre1 = pre
for a in range(n - m + 1):
cur.next = pre
pre = cur
cur = next_node
if cur:
next_node = cur.next
if pre1 != None:
pre1.next = pre
else:
head = pre
cur1.next = cur
return head
3. 两两交换链表中的节点 (24)
题目可以看- 原题地址
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例:
给定 1->2->3->4, 你应该返回 2->1->4->3.
思路:
(1)n1 = p.next
(2)n2 = p.next.next
(3)p.next = n2
(4)n1.next = n2.next
(5)n2.next = n1
(6)p = n1
重复上述6步即可完成两两反转,但是第一二个节点特殊,因为p不能为空,因此设置dummy节点用来占位
class Solution:
def swapPairs(self, head: ListNode) -> ListNode:
dummy = ListNode(0)
dummy.next = head
pre = dummy
while pre.next and pre.next.next:
n1, n2 = pre.next, pre.next.next
pre.next = n2
n1.next = n2.next
n2.next = n1
pre = n1
return dummy.next
4. K 个一组翻转链表 (25)
题目可以看-原题地址
思路:
(1)链表分区为已翻转部分+待翻转部分+未翻转部分
(2)每次翻转前,要确定翻转链表的范围,这个必须通过 k 此循环来确定
(3)需记录翻转链表前驱和后继,方便翻转完成后把已翻转部分和未翻转部分连接起来
初始需要两个变量 pre 和 end,pre 代表待翻转链表的前驱,end 代表待翻转链表的末尾
经过k此循环,end 到达末尾,记录待翻转链表的后继 next = end.next
(4)翻转链表,然后将三部分链表连接起来,然后重置 pre 和 end 指针,然后进入下一次循环
(5)特殊情况,当翻转部分长度不足 k 时,在定位 end 完成后,end==null,已经到达末尾,说明题目已完成,直接返回即可
题目思路借鉴题解原地址
class Solution:
def reverse(self, head):
cur = head
pre = None
next_node = None
while cur:
next_node = cur.next
cur.next = pre
pre = cur
cur = next_node
head = pre
return head
def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
dummy = ListNode(0)
dummy.next = head
pre, end = dummy, dummy
start, next_i = head, head
while next_i:
i = 0
while i < k and end:
end = end.next
i += 1
if not end: break
# 断开链表
start = pre.next
next_i = end.next
end.next = None
# 处理翻转
pre.next = self.reverse(start)
# startNode 转到翻转这部分节点的最后了
# 连接断开的链表
start.next = next_i
# 挪动以进行下一组处理
pre = start
end = pre
return dummy.next
5. 合并两个有序链表 (21)
题目可以看-原题地址
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
思路:
(1)终止条件:当两个链表都为空时,表示我们对链表已合并完成。
(2)如何递归:我们判断 l1 和 l2 头结点哪个更小,然后较小结点的 next 指针指向其余结点的合并结果。(调用递归)
借鉴https://leetcode-cn.com/problems/merge-two-sorted-lists/solution/yi-kan-jiu-hui-yi-xie-jiu-fei-xiang-jie-di-gui-by-/
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
if l1 == None :
return l2
if l2 == None:
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
6. 删除排序链表中的重复元素 (83)
题目可以看-原题地址
给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
示例 2:
输入: 1->1->2->3->3
输出: 1->2->3
思路:
(1)终止条件:当整个链表都没有重复节点时结束。
(2)如何递归:当头节点或者下一个节点不为空时,则调用函数排除重复节点。
(3)头节点之后的节点都是没有重复节点的链表,因此,如果头节点点与下一个节点val相同,则返回head.next。
class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
if head == None or head.next == None :
return head
head.next = self.deleteDuplicates(head.next)
if head.val == head.next.val:
return head.next
else:
return head