给出题目一的试题链接如下:
这一题思路上还是很直接的,就是首先找到给出的数的上下两个10的整倍数,然后找到其中满足题意得那一个,然后求一下和100的差即可。
给出python代码实现如下:
class Solution:
def accountBalanceAfterPurchase(self, purchaseAmount: int) -> int:
a = (purchaseAmount // 10) * 10
b = a + 10
roundedAmount = a if abs(a-purchaseAmount) < abs(b-purchaseAmount) else b
return 100 - roundedAmount
提交代码评测得到:耗时44ms,占用内存16.2MB。
给出题目二的试题链接如下:
这道题原意肯定是考链表,不过这里我偷了个机,直接先转成了array然后进行在恢复成链表,就省去了很多麻烦。
而剩下的就是求一下最大公约数,就不是啥大事了,用python自带的函数即可,当然自己实现也不复杂,就不赘述了。
给出python代码实现如下:
class Solution:
def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:
nodes = []
while head:
nodes.append(head.val)
head = head.next
n = 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。
给出题目三的试题链接如下:
这一题其实想清楚之后还是挺简单的,因为其实最终肯定是要全部变成某一个具体的元素,因此,而要变成某一个元素,其所需的时间事实上就是其他元素到其最近的距离的最大值。
而要求这个值,事实上也就是任意两个相邻的相同同元素之间距离的一半。
因此,我们只需要记录一下每一个元素出现的所有位置,然后对每一个元素计算一下全部变成该元素所需的时间,然后取出最小值即可。
给出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 // 2
dis = [(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。
给出题目四的试题链接如下:
这一题很可惜没能搞定,只是抄了大佬的答案……
思路来说倒是不难理解,或者说多少我也想到了,但是关键部分这样实现为什么可以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个被取用的元素,但是数学上为什么这样就一定能够获得最终的最优答案,多少还是有点想不太清楚,唉……
给出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 i
return -1
提交代码评测得到:耗时1812ms,占用内存16.8MB。