1. 206. 反转链表 https://leetcode.cn/problems/reverse-linked-list/solution/you-xie-cuo-liao-yi-ge-shi-pin-jiang-tou-o5zy/
解题思路:
简单题,需要三个指针, pre,cur,nxt.
pre 是前一个指针, cur是当前指针, nxt是临时指针用于存在当前节点的下一个节点。
反转链表 就是 cur.next = pre pre = cur cur = nxt 直到cur is None循环结束
值得注意的是, 当cur == None pre正好是反转后链表的表头
代码如下
# 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: Optional[ListNode]) -> Optional[ListNode]:
pre, cur = None, head
while cur:
nxt = cur.next
cur.next = pre
pre = cur
cur = nxt
return pre
递归写法
# 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: Optional[ListNode]) -> Optional[ListNode]:
if head is None or head.next is None:
return head
new_head = self.reverseList(head.next)
head.next.next = head
head.next = None
return new_head
递归写法,要有出口! 我们出口是什么? 当找到最后一个节点的时候也就是我们反转后链表的头就是出口!
所以 if head.next is None: return head
第一层归了以后 head.next.next 是什么? head.next 是 最后一个节点, head.next.next = head
就是最后一个节点,指向前一个节点。 head.next = None 前一个节点指向空。
以此类推!!
2. 92. 反转链表 II https://leetcode.cn/problems/reverse-linked-list-ii/solution/you-xie-cuo-liao-yi-ge-shi-pin-jiang-tou-teqq/
解题思路:
反转 [left,right]区间内的全部节点, 那么我们只要找到 第left个节点就可以操作了~
设 P0是 left节点之前的那个节点 当[left, right]区间的所有节点反转结束, cur 指向了 right+1个节点 pre 指向反转后的新头节点。 所以 P0.next.next = cur P0.next = pre。 这样就全部OK了~
值得注意的一点是,当left = 0 P0不存在,故我们可以设一个虚拟头节点dummy,来使得所有情况的left都能实现。
以下是代码
# 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: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
dummy = p0 = ListNode(next = head)
for _ in range(left-1):
p0 = p0.next
cur, pre = p0.next, None
for _ in range(right-left+1):
nxt = cur.next
cur.next = pre
pre = cur
cur = nxt
p0.next.next = cur
p0.next = pre
return dummy.next
3. 25. K 个一组翻转链表 https://leetcode.cn/problems/reverse-nodes-in-k-group/solution/you-xie-cuo-liao-yi-ge-shi-pin-jiang-tou-plfs/
解题思路:
算是对 92 的进阶。 首先计算一下链表中的节点总数,然后如果如果链表中剩余的节点数大于k的话就可以执行92题的操作, 每次循环减少k个节点,并且在循环中应该加入对p0的更新。
每执行一次反转操作,p0.next 恰好就是下一次的p0,所以我们应该提前用一个临时指针存好p0.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]:
cnt = 0
dummy = p0 = ListNode(next = head)
while head:
head = head.next
cnt = cnt + 1
cur, pre = p0.next, None
while cnt >= k:
cnt -= k
for _ in range(k):
nxt = cur.next
cur.next = pre
pre = cur
cur = nxt
nxt = p0.next
p0.next.next = cur
p0.next = pre
p0 = nxt
return dummy.next
4. 24. 两两交换链表中的节点 https://leetcode.cn/problems/swap-nodes-in-pairs/
解题思路:
两两交换? 不就是两个一组反转链表吗! 直接套用上面的代码即可!
# 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: Optional[ListNode]) -> Optional[ListNode]:
cnt = 0
cur = head
while cur:
cnt += 1
cur = cur.next
dummy = p0 = ListNode(next = head)
pre, cur = None, head
while cnt >= 2:
cnt -= 2
for _ in range(2):
nxt = cur.next
cur.next = pre
pre = cur
cur = nxt
nxt = p0.next
p0.next.next = cur
p0.next = pre
p0 = nxt
return dummy.next
5. 2.两数相加 https://leetcode.cn/problems/add-two-numbers/
解题思路:
利用一个carry变量存l1 和 l2 以及 进位的和。
每次 将carry % 10 赋值给新节点
然后更新 carry = carry // 10
# 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]:
# 用来保存进位
carry = 0
# 创建一个新链表,用来存两数相加的结果
dummy = l3 = ListNode()
# l1 不为空 or l2 不为空 or 进位不为0 循环就继续
while l1 or l2 or carry:
carry = (l1.val if l1 else 0) + (l2.val if l2 else 0) + carry
l3.next = ListNode(val = carry % 10)
carry = carry // 10
if l1:
l1 = l1.next
if l2:
l2 = l2.next
l3 = l3.next
return dummy.next
6. 445. 两数相加 II
解题思路:
先翻转,再相加
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
def reverse_list(head):
if head is None or head.next is None:
return head
new_head = reverse_list(head.next)
head.next.next = head
head.next = None
return new_head
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
new_l1 = reverse_list(l1)
new_l2 = reverse_list(l2)
carry = 0
dummy = l3 = ListNode()
while new_l1 or new_l2 or carry:
carry = (new_l1.val if new_l1 else 0) + (new_l2.val if new_l2 else 0) + carry
l3.next = ListNode(val = carry % 10)
carry = carry // 10
l3 = l3.next
if new_l1:
new_l1 = new_l1.next
if new_l2:
new_l2 = new_l2.next
return reverse_list(dummy.next)
7.2816. 翻倍以链表形式表示的数字
解题思路:
两数相加|| ---> 自己和自己相加
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
def reverse_list(head):
if head is None or head.next is None:
return head
new_head = reverse_list(head.next)
head.next.next = head
head.next = None
return new_head
class Solution:
def doubleIt(self, head: Optional[ListNode]) -> Optional[ListNode]:
carry = 0
l1 = reverse_list(head)
dummy = l2 = ListNode()
while l1 or carry:
carry = (l1.val if l1 else 0)*2 + carry
l2.next = ListNode(val = carry % 10)
carry = carry // 10
l2 = l2.next
if l1:
l1 = l1.next
return reverse_list(dummy.next)