Leetcode周赛 | 2023-7-24

文章介绍了几道编程题的解决方案,包括找到数组中的最大值、任务调度的最短时间计算以及回文路径计数。在任务调度问题中,重点在于确定出现最频繁的任务并计算最短完成时间。在其他题目中,代码实现了倒序遍历、排序和位运算等算法技巧。
摘要由CSDN通过智能技术生成

题1

在这里插入图片描述

体会

想到倒序遍历就可以。

我的代码

class Solution:
    def maxArrayValue(self, nums: List[int]) -> int:
        n = len(nums)
        i = n-1
        while i > 0 :
            if nums[i]>=nums[i-1]:
                i -= 1
                nums[i] += nums[i+1]
            else :
                i-=1
        return max(nums)

题2

在这里插入图片描述
在这里插入图片描述

这道题是一点都不会

重点

在这里插入图片描述

class Solution:
    def maxIncreasingGroups(self, x: List[int]) -> int:
        x.sort()
        n = len(x)
        curr = 0
        ans = 0
        for v in x:
            curr += v
            if curr >= ans + 1:
                ans += 1
                curr -= ans
        return ans

我的代码

题3

在这里插入图片描述
在这里插入图片描述

重点

在这里插入图片描述

class Solution:
    def countPalindromePaths(self, parent: List[int], s: str) -> int:
        n = len(parent)
        @cache
        def getRes(idx):
            if idx == 0: return 0
            return getRes(parent[idx]) ^ (1 << (ord(s[idx]) - ord('a')))
        vals = [getRes(i) for i in range(n)]
        cnt = Counter()
        ans = 0
        for x in vals:
            ans += cnt[x]
            for i in range(26):
                ans += cnt[x ^ (1 << i)]
            cnt[x] += 1
        return ans

我的代码

题二题三都不会

621. 任务调度器

在这里插入图片描述

思路

完成所有任务的最短时间取决于出现次数最多的任务数量。

看下题目给出的例子

输入: tasks = [“A”,“A”,“A”,“B”,“B”,“B”], n = 2
输出: 8
执行顺序: A -> B -> (待命) -> A -> B -> (待命) -> A -> B.
因为相同任务必须要有时间片为 n 的间隔,所以我们先把出现次数最多的任务 A 安排上(当然你也可以选择任务 B)。例子中 n = 2,那么任意两个任务 A 之间都必须间隔 2 个单位的时间:

A -> (单位时间) -> (单位时间) -> A -> (单位时间) -> (单位时间) -> A
中间间隔的单位时间可以用来安排别的任务,也可以处于“待命”状态。当然,为了使总任务时间最短,我们要尽可能地把单位时间分配给其他任务。现在把任务 B 安排上:

A -> B -> (单位时间) -> A -> B -> (单位时间) -> A -> B
很容易观察到,前面两个 A 任务一定会固定跟着 2 个单位时间的间隔。最后一个 A 之后是否还有任务跟随取决于是否存在与任务 A 出现次数相同的任务。

该例子的计算过程为:

(任务 A 出现的次数 - 1) * (n + 1) + (出现次数为 3 的任务个数),即:

(3 - 1) * (2 + 1) + 2 = 8
所以整体的解题步骤如下:

计算每个任务出现的次数
找出出现次数最多的任务,假设出现次数为 x
计算至少需要的时间 (x - 1) * (n + 1),记为 min_time
计算出现次数为 x 的任务总数 count,计算最终结果为 min_time + count
特殊情况
然而存在一种特殊情况,例如:

输入: tasks = [“A”,“A”,“A”,“B”,“B”,“B”,“C”,“C”,“D”,“D”], n = 2
输出: 10
执行顺序: A -> B -> C -> A -> B -> D -> A -> B -> C -> D
此时如果按照上述方法计算将得到结果为 8,比数组总长度 10 要小,应返回数组长度。

class Solution(object):
    def leastInterval(self, tasks, n):
        """
        :type tasks: List[str]
        :type n: int
        :rtype: int
        """
        length = len(tasks)
        if length <= 1:
            return length
        
        # 用于记录每个任务出现的次数
        task_map = dict()
        for task in tasks:
            task_map[task] = task_map.get(task, 0) + 1
        # 按任务出现的次数从大到小排序
        task_sort = sorted(task_map.items(), key=lambda x: x[1], reverse=True)
        
        # 出现最多次任务的次数
        max_task_count = task_sort[0][1]
        # 至少需要的最短时间
        res = (max_task_count - 1) * (n + 1)
        
        for sort in task_sort:
            if sort[1] == max_task_count:
                res += 1
        
        # 如果结果比任务数量少,则返回总任务数
        return res if res >= length else length

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值