Leetcode刷题日记-链表(二)

1. 剑指Offer-24 实现链表反转 (206)

题目可以看-原题地址

  1. 三个指针翻转
    思路
    (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 

  1. 递归
    在这里插入图片描述
   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
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值