LeetCode之算法面试之链表1之反转链表(206)、反转链表II(92)、删除排序链表中的重复元素(83)、分隔链表(86)

1、反转链表(206)

题目描述:

【简单题】
在这里插入图片描述

题目链接

思路分析

题解一:迭代

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
1、通过上图分析,反转链表相当于改变每一节点的next指针为前一节点。由于在转变过程中,涉及到前一节点,当前节点,遍历完当前节点转场的下一节点,则可以设置三个指针(pre前指针,cur当前指针,nxt下一指针),从而实现反转。

2、初始pre为空指针,代表前一节点;cur为头节点head,代表当前节点;

3、当前节点cur不为空时,进行循环:

  • 下一节点nxt=cur.next
  • 当前节点的指针为前一节点pre,实现局部反转。
  • 移动前一节点pre为当前节点cur
  • 移动当前节点cur为下一节点

4、返回链表即头节点pre

【python3实现代码】

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        pre=None
        cur=head
        while cur:
            nxt=cur.next
            cur.next=pre
            pre=cur
            cur=nxt
        return pre
  • 时间复杂度: O ( n ) O(n) O(n),假设 n n n 是列表的长度,
  • 空间复杂度: O ( 1 ) O(1) O(1)

题解二:递归
在这里插入图片描述

1、递归就是调用自己的函数,对于此题来说:相对于现头结点来说,它只需要知道它之后的所有节点反转之后的结果就可以了,也就是说递推公式reverseList的含义是:把拿到的链表进行反转,然后返回新的头结点。

在这里插入图片描述
2、再反转头结点:head.next.next=head,head.next=None

代码实现:

# 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: ListNode) -> ListNode:
        if head is None or head.next is None:
            return head
        newhead=self.reverseList(head.next)
        head.next.next=head
        head.next=None
        return newhead
  • 时间复杂度:O(n),其中 n 是链表的长度。需要对链表的每个节点进行反转操作。

  • 空间复杂度:O(n),其中 n 是链表的长度。空间复杂度主要取决于递归调用的栈空间,最多为 n 层。

2、反转链表II(92)

题目描述:

【中等题】
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。

在这里插入图片描述
题目链接

思路分析

题解一:迭代

此题与上一题的区别是仅区间内反转,所以相对于上题需做以下两步:

  • 找到m位置的节点和m位置的前置节点pre
  • 另外,我们要引入两个额外指针,分别称为 tail 和 con。tail 指针指向从链表头起的第m个结点,此结点是反转后子链表的尾部,故称为 tail。con 指针指向第 m 个结点的前一个结点,此结点是新链表的头部。下图可以帮助你更好的理解这两个指针。利用两指针调整链表。

在这里插入图片描述

  • 当区间内的链表进行反转后,我们使用 con 指针来连接 prev 指针,这是因为 prev 指针当前指向的结点(第 n 个结点)会代替第 m 个结点的位置。 类似地,我们利用 tail 指针来连接 prev 指针之后的结点(第 n+1 个结点)。
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
        if not head:
            return None
        pre,cur,i=None,head,1
        while i<m:
            pre=cur
            cur=cur.next
            i+=1
        tail,con=cur,pre
        while i<=n:
            nxt=cur.next
            cur.next=pre
            pre=cur
            cur=nxt
            i+=1
        if con:
            con.next,tail.next=pre,cur
            return head
        else:
            tail.next=cur
            head=pre
            return head
  • 时间复杂度: O ( n ) O(n) O(n),假设 n n n 是列表的长度,

  • 空间复杂度: O ( 1 ) O(1) O(1)

题解二:递归

思路:
代码实现:

# 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: ListNode, left: int, right: int) -> ListNode:
        if left==1:
            return self.reverseTopN(head,right)
        between = self.reverseBetween(head.next, left-1,right-1)
        head.next = between
        return head

    topNSuccessor=None
    #定义反转前n个节点链表
    def reverseTopN(self, head: ListNode, right: int) -> ListNode:
        global topNSuccessor #全局变量
        if right==1:
            topNSuccessor=head.next
            return head
        
        newhead=self.reverseTopN(head.next,right-1)
        head.next.next=head
        head.next=topNSuccessor
        return newhead

3、删除排序链表中的重复元素(83)

题目描述:

【简单题】
给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
在这里插入图片描述

题目链接

思路分析

1.由于链表已经排序,删除重复元素,只需从前到后判断当前元素是否与后面元素重复,若重复,删除其中一个即可
2.由于链表结点的特征性,因此我们可以通过将当前结点的值与它之后的结点进行比较来确定它是否为重复结点。可设置一个当前节点指针cur

  • 如果它是重复的,我们更改当前结点cur的 next 指针为cur.next.next,以便它跳过下一个结点并直接指向下一个结点之后的结点。
  • 如果不是重复的,则将cur指针移动到下一位置即cur.next。
    关键点:指针的是否改变

【python3 实现】

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        if not head:
            return None
        cur=head
        while cur.next:
            if cur.val==cur.next.val:
                cur.next=cur.next.next
            else:
                cur=cur.next
        return head

4、分隔链表(86)

题目描述:

【中等题】
给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。

你应当保留两个分区中每个节点的初始相对位置。
在这里插入图片描述

题目链接

思路分析

1、大小链表,最后拼接

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def partition(self, head: ListNode, x: int) -> ListNode:
        dummy1 = ListNode(-1)
        dummy2 = ListNode(-1)
        p1 = dummy1
        p2 = dummy2
        while head:
            if head.val < x:
                p1.next = head
                p1 = p1.next
            else:
                p2.next = head
                p2 = p2.next
            head = head.next
        
        p1.next = dummy2.next
        p2.next = None
        return dummy1.next
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值