[算法学习06] 反转链表

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)

  • 18
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值