[英雄星球六月集训LeetCode解题日报] 第12日 链表

一、 328. 奇偶链表

链接: 328. 奇偶链表

1. 题目描述

给定单链表的头节点 head ,将所有索引为奇数的节点和索引为偶数的节点分别组合在一起,然后返回重新排序的列表。

第一个节点的索引被认为是 奇数 , 第二个节点的索引为 偶数 ,以此类推。

请注意,偶数组和奇数组内部的相对顺序应该与输入时保持一致。

你必须在 O(1) 的额外空间复杂度和 O(n) 的时间复杂度下解决这个问题
在这里插入图片描述

2. 思路分析

要求奇偶分开,因此一次处理两个节点,那我们就设置两个指针一起后移即可。
最后把两段连起来,因此一开始要记录一下偶指针的头。

3. 代码实现

class Solution:
    def oddEvenList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if not head or not head.next or not head.next.next:
            return head
        zero = head
        one = one0= head.next
        while one and one.next:        
            zero.next = one.next
            zero = zero.next                       
            one.next = zero.next
            one = one.next

        zero.next = one0

        return head

二、 725. 分隔链表

链接: 725. 分隔链表

1. 题目描述

给你一个头结点为 head 的单链表和一个整数 k ,请你设计一个算法将链表分隔为 k 个连续的部分。

每部分的长度应该尽可能的相等:任意两部分的长度差距不能超过 1 。这可能会导致有些部分为 null 。

这 k 个部分应该按照在链表中出现的顺序排列,并且排在前面的部分的长度应该大于或等于排在后面的长度。

返回一个由上述 k 部分组成的数组。
在这里插入图片描述

2. 思路分析

  • 有点像微信的抢红包算法,每次分配:用当前剩余数量除以剩余格子,
  • 计算一个当前的平均值,本题向上取整可保证非升序。
  • 更新剩余数量和剩余格子个数。

3. 代码实现

class Solution:
    def splitListToParts(self, head: ListNode, k: int) -> List[ListNode]:
        if not head :
            return [head]*k
        cur = head
        list_copy = []
        while cur:
            list_copy.append(cur)
            cur = cur.next
        length = len(list_copy)
        
        ans = []
        i = j = 0  # 数组指针,剩余格子指针
        while j < k:
            width = ceil((length-i)/(k-j))  # 当前宽度=剩余长度/剩余格子
            x = list_copy[i] if i < length else None
            ans.append(x)
            i += width
            if i-1 < length:
                list_copy[i-1].next = None
            j += 1
        return ans

三、 817. 链表组件

链接: 817. 链表组件

1. 题目描述

给定链表头结点 head,该链表上的每个结点都有一个 唯一的整型值 。同时给定列表 nums,该列表是上述链表中整型值的一个子集。

返回列表 nums 中组件的个数,这里对组件的定义为:链表中一段最长连续结点的值(该值必须在列表 nums 中)构成的集合。

在这里插入图片描述

2. 思路分析

从例2来看,nums是无序的,可以排序后组合出连续子集也算满足要求。
那么实际上就是求nums中连续的数据组数。
由于链表的数据也是乱序的,因此转换成下标即可。
然后把nums的数转换成链表中映射的下标。

3. 代码实现

class Solution:
    def numComponents(self, head: Optional[ListNode], nums: List[int]) -> int:
        d = {}
        depth = 0
        while head:
            d[head.val] = depth
            depth+= 1
            head = head.next
        poses = []
        for num in nums:
            if num in d:
                poses.append(d[num])
        poses.sort()
        n = len(poses)
        cnt = [poses[0]]
        for i in range(1,n):
            if poses[i]-poses[i-1]>1:
                cnt.append(poses[i])
        return len(cnt)

四、 622. 设计循环队列

链接: 622. 设计循环队列

1. 题目描述

在这里插入图片描述

2. 思路分析

题意比较明确。
本题必然是用链表设置头尾虚拟节点最简单,但不符合题意,因为链表的节点申请是重新分配内存的。
题目显然是考察数组模拟,否则没难度了。

  • 如果也用头尾指针模拟,可以数组开成k+2,比较好写。(因为头尾指针也要占位置)
  • 但是最好写的还是头指针+size,判empty和full都是一行

3. 代码实现

class MyCircularQueue:

    def __init__(self, k: int):
        self.que = [0] *k
        self.k = k
        self.head = 0
        self.count = 0

    def enQueue(self, value: int) -> bool:        
        if self.isFull():
            return False
        k = self.k
        idx = self.head +self.count
        if idx >= k:
            idx -= k
        self.que[idx] = value
        self.count += 1
        return True

    def deQueue(self) -> bool:
        if self.isEmpty():
            return False
        k = self.k
        self.head += 1
        if self.head >= k:
            self.head -= k
        self.count -= 1
        return True

    def Front(self) -> int:     
        if self.isEmpty():
            return -1   
        return self.que[self.head]

    def Rear(self) -> int:
        if self.isEmpty():
            return -1   
        idx = self.head + self.count - 1 
        return self.que[(idx+self.k)%self.k]

    def isEmpty(self) -> bool:
        return self.count == 0

    def isFull(self) -> bool:
        return self.count == self.k
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值