LeetCode笔记:Weekly Contest 214 比赛记录

  • LeetCode笔记:Weekly Contest 214
    • 0. 赛后总结
    • 1. 题目一
      • 1. 解题思路
      • 2. 代码实现
    • 2. 题目二
      • 1. 解题思路
      • 2. 代码实现
    • 3. 题目三
      • 1. 解题思路
      • 2. 代码实现
    • 4. 题目四
      • 1. 解题思路
      • 2. 代码实现

0. 赛后总结

这次的比赛因为要搬家就没有参加,晚上的时候参加了一下模拟竞赛,结果中奖了,模拟竞赛直接打到了世界68名,不过这次不知道为啥参加人数好少,全世界只有6000多人参赛,几乎只有平时的1/2,不知道发生了啥。。。

btw,不搬家是真的不知道东西多,搬家真心好累啊,唉。。。

1. 题目一

给出题目一的试题链接如下:

  • 1646. Get Maximum in Generated Array

1. 解题思路

这题是一道easy的题目,然而我翻车了。。。

原因在于想当然了,想着按照题目的生成规则,最大的数一定是最邻近的一个奇数计算得到的,然而事实并不是。

后来考虑到n只能取到100,因此,我们直接暴力遍历一遍就行了,事实上,这也就是一个可行的代码实现。

2. 代码实现

我们直接给出代码实现如下:

class Solution:
    def getMaximumGenerated(self, n: int) -> int:
        
        @lru_cache(None)
        def f(n):
            if n <= 1:
                return n
            if n % 2 == 0:
                ans = f(n // 2)
            else:
                ans = f(n // 2) + f(n // 2 + 1)
            return ans
            
        return max(f(x) for x in range(n+1))

提交代码评测得到:耗时32ms,占用内存14.4MB。

这里,由于当前的提交记录不够,我们暂时不知道有没有更好的解答,不过盲猜肯定是有的,有兴趣的读者可以考虑一下对于任意一个整数n,当 x x x取到多少时可以令 f ( x ) f(x) f(x)取到最大值。

想清楚这个问题的话应该能够进一步优化代码实现效率。

2. 题目二

给出题目二的试题链接如下:

  • 1647. Minimum Deletions to Make Character Frequencies Unique

1. 解题思路

这一题的解题思路其实也蛮直接的,我们首先统计字符串中的各个字符的频数,然后令其不会重复,看需要删除的最小字符个数。

我们首先对其频数进行排序,对于其中任意一个存在重复的频数,我们将以进行减一操作,直至数组中不存在与之相同的频数或者变为0,此时所需要执行的操作就是最少需要执行的操作次数。

累加所有的重复频数所对应的操作数,即可得到最终的答案。

2. 代码实现

给出python代码实现如下:

class Solution:
    def minDeletions(self, s: str) -> int:
        counter = sorted(Counter(s).values())
        if len(counter) <= 1:
            return 0
        ans = 0
        seen = set()
        for c in counter:
            if c not in seen:
                seen.add(c)
                continue
            while c in seen and c > 0:
                c -= 1
                ans += 1
            if c > 0:
                seen.add(c)
        return ans

提交代码评测得到:耗时116ms,占用内存14.9MB。

当前最优的代码实现耗时112ms,原因在于他对于最小不重复数的搜索过程进行了优化,但核心思路上两者是一样的。

有兴趣的读者可以自行研究一下他们对于检索过程的优化代码,真心巧妙。

3. 题目三

给出题目三的试题链接如下:

  • 1648. Sell Diminishing-Valued Colored Balls

1. 解题思路

这一题的思路其实还是蛮直接的,因为每一次出售的最优策略一定是出售当前最多颜色的球。每次重复这一操作即可。

当然,显而易见的,如果我们真的来一个暴力地循环,那必然会有超时问题,因此,我们首先对不同颜色的球的个数进行统计,将相同数目但是不同颜色的球合并为一个batch,共同进行操作。

显然,假设当前相同颜色最多的球数目有 n n n个,其种类有 k k k种,而次多颜色的球的数目为 m m m个,其种类有 k ′ k' k种,那么,我们有如下两种情况:

  1. 所剩余的orders次数足以将所有的 k k k种颜色的球全部卖到只剩 m m m个球,那么我们就将其全部卖至只剩 m m m个球,然后合并所有数目为 m m m的球。

    此时有 o r d e r s > = k × ( n − m ) orders >= k \times (n-m) orders>=k×(nm),而销售额变化为:

    s e l l = s e l l + k × ( n + m + 1 ) × ( n − m ) / 2 sell = sell + k \times (n+m+1) \times (n-m) / 2 sell=sell+k×(n+m+1)×(nm)/2

  2. 所剩余的orders次数不足以将所有的 k k k种颜色的球全部卖到只剩 m m m个球,那么我们首先按批次逐个将各个颜色的球均匀的卖至所有操作全部用完即可。

    此时有: o r d e r s < k × ( n − m ) orders < k \times (n-m) orders<k×(nm)。令 α = ⌊ o r d e r s k ⌋ \alpha = \lfloor \frac{orders}{k} \rfloor α=korders β = o r d e r s − α × k \beta = orders - \alpha \times k β=ordersα×k,则有:

    s e l l = s e l l + k × ( n + α + 1 ) × ( n − α ) / 2 + β × α sell = sell + k \times (n + \alpha + 1) \times (n - \alpha) / 2 + \beta \times \alpha sell=sell+k×(n+α+1)×(nα)/2+β×α

我们将上述过程翻译至python语言即可得到我们最终的代码。

2. 代码实现

给出我们最终的python代码实现如下:

class Solution:
    def maxProfit(self, inventory: List[int], orders: int) -> int:
        MOD = 10**9+7
        inventory = [(0, 0)] + sorted(Counter(inventory).items())
        ans = 0
        while orders > 0:
            # print(inventory, orders)
            diff = inventory[-1][0] - inventory[-2][0]
            if diff * inventory[-1][1] <= orders:
                orders -= diff * inventory[-1][1]
                ans = (ans + inventory[-1][1] * (2 * inventory[-1][0] - diff + 1) * diff // 2) % MOD
                n, c = inventory.pop()
                inventory[-1] = (inventory[-1][0], inventory[-1][1] + c)
            else:
                diff = orders // inventory[-1][1]
                ans = (ans + inventory[-1][1] * (2 * inventory[-1][0] - diff + 1) * diff // 2 + (inventory[-1][0] - diff) * (orders % inventory[-1][1])) % MOD
                orders = 0
        return ans

提交代码评测得到:耗时720ms,占用内存35.9MB。

当前最优代码实现耗时604ms,但是看了一下感觉思路是相同的,因此这里就不过多展开了。

4. 题目四

给出题目四的试题链接如下:

  • 1649. Create Sorted Array through Instructions

1. 解题思路

这次的最后一题感觉特别的简单,无非就是不停地使用二分查找找到比当前元素大的和小的元素的数目,然后取小值。

进一步地,使用python的bisect库之后,这道题就更加简单了。

2. 代码实现

我们直接给出python的代码实现如下:

class Solution:
    def createSortedArray(self, instructions: List[int]) -> int:
        MOD = 10**9 + 7
        cache = []
        n = 0
        ans = 0
        for k in instructions:
            i, j = bisect.bisect_left(cache, k), bisect.bisect_right(cache, k)
            ans = (ans + min(i, (n-j))) % MOD
            bisect.insort(cache, k)
            n += 1
        return ans

提交代码评测得到:耗时8368ms,占用内存27.9MB。

当前的最优代码实现耗时3880ms,但是看了一下他们的思路和我们是完全一样的,唯一的区别在于他在排序过程中使用了另外一种有序数列的结构,给出他们的代码实现如下:

from sortedcontainers import SortedList

class Solution:
    def createSortedArray(self, instructions: List[int]) -> int:
        ans = 0
        a = SortedList()
        
        for i in instructions:
            cost1 = a.bisect_left(i)
            cost2 = len(a) - a.bisect_right(i)
            ans += min(cost1, cost2)
            a.add(i)
        
        return ans % 1000000007

本质而言我是没有看出什么太大的差别。。。

你可能感兴趣的:(leetcode笔记,leetcode,算法,python)