- LeetCode笔记:Biweekly Contest 110
- 1. 题目一
- 1. 解题思路
- 2. 代码实现
- 2. 题目二
- 1. 解题思路
- 2. 代码实现
- 3. 题目三
- 1. 解题思路
- 2. 代码实现
- 4. 题目四
- 1. 解题思路
- 2. 代码实现
- 1. 题目一
- 比赛链接:https://leetcode.com/contest/biweekly-contest-110
1. 题目一
给出题目一的试题链接如下:
- 2806. Account Balance After Rounded Purchase
1. 解题思路
这一题思路上还是很直接的,就是首先找到给出的数的上下两个10的整倍数,然后找到其中满足题意得那一个,然后求一下和100的差即可。
2. 代码实现
给出python代码实现如下:
class Solution:def accountBalanceAfterPurchase(self, purchaseAmount: int) -> int:a = (purchaseAmount // 10) * 10b = a + 10roundedAmount = a if abs(a-purchaseAmount) < abs(b-purchaseAmount) else breturn 100 - roundedAmount
提交代码评测得到:耗时44ms,占用内存16.2MB。
2. 题目二
给出题目二的试题链接如下:
- 2807. Insert Greatest Common Divisors in Linked List
1. 解题思路
这道题原意肯定是考链表,不过这里我偷了个机,直接先转成了array然后进行在恢复成链表,就省去了很多麻烦。
而剩下的就是求一下最大公约数,就不是啥大事了,用python自带的函数即可,当然自己实现也不复杂,就不赘述了。
2. 代码实现
给出python代码实现如下:
class Solution:def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:nodes = []while head:nodes.append(head.val)head = head.nextn = len(nodes)for i in range(n-1):a = nodes[2*i]b = nodes[2*i+1]nodes.insert(2*i+1, gcd(a,b))nodes = [ListNode(val) for val in nodes]n = len(nodes)for i in range(n-1):nodes[i].next = nodes[i+1]return nodes[0]
提交代码评测得到:耗时123ms,占用内存21.5MB。
3. 题目三
给出题目三的试题链接如下:
- 2808. Minimum Seconds to Equalize a Circular Array
1. 解题思路
这一题其实想清楚之后还是挺简单的,因为其实最终肯定是要全部变成某一个具体的元素,因此,而要变成某一个元素,其所需的时间事实上就是其他元素到其最近的距离的最大值。
而要求这个值,事实上也就是任意两个相邻的相同同元素之间距离的一半。
因此,我们只需要记录一下每一个元素出现的所有位置,然后对每一个元素计算一下全部变成该元素所需的时间,然后取出最小值即可。
2. 代码实现
给出python代码实现如下:
class Solution:def minimumSeconds(self, nums: List[int]) -> int:n = len(nums)locs = defaultdict(list)for i, x in enumerate(nums):locs[x].append(i)def get_seconds(indexs):m = len(indexs)if m == 1:return n // 2dis = [(indexs[i] - indexs[i-1] + n) % n // 2 for i in range(m)]return max(dis)seconds = [get_seconds(indexs) for indexs in locs.values()]return min(seconds)
提交代码评测得到:耗时640ms,占用内存49.1MB。
4. 题目四
给出题目四的试题链接如下:
- 2809. Minimum Time to Make Array Sum At Most x
1. 解题思路
这一题很可惜没能搞定,只是抄了大佬的答案……
思路来说倒是不难理解,或者说多少我也想到了,但是关键部分这样实现为什么可以work就多少有点不太理解了,这里就只是把大佬的思路先写下来,后来有空再回来看看吧……
整体的思路上来说其实还是挺简单的,显然,假设两个数组的和分别为 s 1 , s 2 s_1, s_2 s1,s2,那么如果经过 k k k次操作,其最终的答案一定是:
f ( k ) = s 1 + k ⋅ s 2 − ∑ i = 1 k ( a n i + k ⋅ b n i ) f(k) = s_1 + k \cdot s_2 - \sum\limits_{i=1}^{k} (a_{n_i} + k \cdot {b_{n_i}}) f(k)=s1+k⋅s2−i=1∑k(ani+k⋅bni)
然后,这里的变量其实就是后面的 ∑ i = 1 k ( a n i + k ⋅ b n i ) \sum\limits_{i=1}^{k} (a_{n_i} + k \cdot {b_{n_i}}) i=1∑k(ani+k⋅bni)部分,要使得整体的 f ( k ) f(k) f(k)最小,就是令 ∑ i = 1 k ( a n i + k ⋅ b n i ) \sum\limits_{i=1}^{k} (a_{n_i} + k \cdot {b_{n_i}}) i=1∑k(ani+k⋅bni)取最大。其中, n i n_i ni是一组坐标的下标选择。
但是,我自己的话就是卡在这里做不下去了,不知道怎么去做这个问题,然后看大佬们的答案倒是思路也简单,就是在这里用了动态规划,定义 f n ( k ) \mathop{f_n}(k) fn(k)表示经过 k k k次操作之后能够获得的 ∑ i = 1 k ( a n i + k ⋅ b n i ) \sum\limits_{i=1}^{k} (a_{n_i} + k \cdot {b_{n_i}}) i=1∑k(ani+k⋅bni)的最大值,然后动态规划的求取这个 f n ( k ) \mathop{f_n}(k) fn(k)。
但是,就是关于这里为什么大佬们给出的动态规划方式可以work多少有点感觉奇怪,其实现上很简单:
-
首先对于位置关于 ( b i , a i ) (b_i, a_i) (bi,ai)的大小进行排序;
-
然后从小到大分别取出每一组 ( b i , a i ) (b_i, a_i) (bi,ai),依次更新所有的 f n ( k ) \mathop{f_n}(k) fn(k)为:
f n ( k ) = m a x ( f n ( k ) , f n ( k − 1 ) + a i + k ⋅ b i ) \mathop{f_n}(k) = \mathop{max}(\mathop{f_n}(k), \mathop{f_n}(k-1) + a_i + k\cdot b_i) fn(k)=max(fn(k),fn(k−1)+ai+k⋅bi)
这个递推表达式本身也不难理解,就是对每一个元素,考察是否要取用这个元素作为第 k k k个被取用的元素,但是数学上为什么这样就一定能够获得最终的最优答案,多少还是有点想不太清楚,唉……
2. 代码实现
给出python代码实现如下:
class Solution:def minimumTime(self, nums1: List[int], nums2: List[int], x: int) -> int:n = len(nums1)nums = sorted([(b, a) for a, b in zip(nums1, nums2)])fn = [0 for _ in range(n+1)]for b, a in nums:for i in range(n, 0, -1):fn[i] = max(fn[i], fn[i-1] + a+i*b)s1 = sum(nums1)s2 = sum(nums2)for i in range(n+1):if s1 + s2*i - fn[i] <= x:return ireturn -1
提交代码评测得到:耗时1812ms,占用内存16.8MB。