这一次的比赛怎么说呢,感觉有点不尴不尬的。
要说吧,4道题也都做出来了,耗时老实说也没有特别长,不算错误惩罚的话其实也就56分钟,不到1个小时,整体虽然没有挤进国内前100,好歹也有前4%(116/3682),世界排名也是311/9290,也属于前4%,照说应该是一次不错的发挥了。
但是吧,就是感觉不舒服,第三题第四题做的实在太纠结了,尤其是第三题,虽然说一次过了,但是用的是最暴力的迭代算法,讲道理能过完全是运气好,我本来完全没报希望的,只是因为实在想不到更好的算法了。
第四题也是,虽说最后以两次错误的代价提交成功了,但是看错题目实在是硬伤,而且算法也不算多少优雅,还是用的非常暴力的迭代求解的算法。
唉,回头等比赛结束之后好好地研究一下别人的解法学习一下吧。
给出题目一的试题链接如下:
这一题思路很直接,就是直接按照规则一路往下就行了。
给出python代码实现如下:
class Solution:
def numberOfMatches(self, n: int) -> int:
res = 0
while n != 1:
res += n // 2
n = (n+1) // 2
return res
提交代码评测得到:耗时20ms,占用内存14.3MB。属于当前最优代码实现。
给出题目二的试题链接如下:
这一题乍看之下有点复杂,但其实仔细一想异常简单,显然,由于二进制数只能由1、0组成,因此,对于任意一个数,假设这个数字中最大的比特数为k,则至少需要k个十-二进制数才能够分解这个数字。
而另一方面,如果我们采用如下规则进行数字拆解:
重复上述操作,可以看到,当k次操作之后,总能够将这个数字变为0。
综上,k就是最终的答案。
因此,我们可以快速地给出python代码实现如下:
class Solution:
def minPartitions(self, n: str) -> int:
return max(int(x) for x in n)
提交代码评测得到:耗时188ms,占用内存14.7MB。
当前的最优代码实现耗时仅52ms,但是本质来说算法思路是完全一致的,不过他们没有将每一个bit都进行整形转换,而是利用了ascii码中的顺序关系简化了代码。
给出他们的代码实现如下:
class Solution:
def minPartitions(self, n: str) -> int:
return ord(max(n)) - ord('0')
给出题目三的试题链接如下:
这一题比赛中我是用最为暴力地迭代方法进行求解的,因为递推公式还是很好写出来的。
假设在每一轮操作(Alice和Bob各自进行一次操作)当中,Alice选择的元素为 a a a,Bob选择的元素为 b b b,而在他们进行操作之前的元素总和为 s s s,则Alice得分为 s − a s-a s−a,Bob的得分为 s − a − b s-a-b s−a−b,该轮操作导致的两人的分差变化为 b b b
因此,我们可以快速地写出每一次操作的递推公式如下:
dp(i, j) = max(min(stones[j]+dp(i+1, j-1), stones[i+1] + dp(i+2, j)), min(stones[i]+dp(i+1, j-1), stones[j-1] + dp(i, j-2)))
其中,四种情况分别代表:
给出python代码实现如下:
class Solution:
def stoneGameVII(self, stones: List[int]) -> int:
@lru_cache(None)
def dp(st, ed):
if st >= ed:
return 0
else:
return max(min(stones[ed]+dp(st+1, ed-1), stones[st+1] + dp(st+2, ed)), min(stones[st]+dp(st+1, ed-1), stones[ed-1] + dp(st, ed-2)))
return dp(0, len(stones)-1)
提交代码评测得到:耗时4480ms,占用内存608.7MB。
当前的最优代码实现耗时4092ms,而且看他的实现也没觉得多好,但是我总觉得应该有更加优雅的实现方法,唉,过两天再看看有没有更好的解法吧。
给出题目四的试题链接如下:
这一题坦率地说感觉也是应该有更好的解题方法的,可惜我这边实在是没想到什么更好更优雅的解题方法,只能用暴力求解的方法硬怼。
不过幸运的是,终究还是怼出来了就是了。
对于这一题,核心在于两点:
首先,由于题目限制说一个长方体 j j j要能够叠放在另一个长方体 i i i的话,要求:
{ w i ≥ w j l i ≥ l j h i ≥ h j \left\{ \begin{aligned} w_i &\geq w_j \\ l_i &\geq l_j \\ h_i &\geq h_j \end{aligned} \right. ⎩⎪⎨⎪⎧wilihi≥wj≥lj≥hj
因此,我们对长方体按照边长进行排序,显然最终的结果必然是排序后结果的一个子序列。
另一方面,我们来讨论递推关系,他有以下一些情况:
综上,我们就可以给出最终的递推关系。
给出python的代码实现如下:
class Solution:
def maxHeight(self, cuboids: List[List[int]]) -> int:
n = len(cuboids)
cuboids = sorted([sorted(x, reverse=True) for x in cuboids], reverse=True)
# print(cuboids)
@lru_cache(None)
def dp(idx, a, b, c):
if idx >= n:
return 0
res = dp(idx+1, a, b, c)
aa, bb, cc = cuboids[idx]
if cc <= c and ((aa <= a and bb <= b) or (aa <= b and bb <= a)):
res = max(res, cc + dp(idx+1, aa, bb, cc))
if bb <= c and ((aa <= a and cc <= b) or (aa <= b and cc <= a)):
res = max(res, bb + dp(idx+1, aa, cc, bb))
if aa <= c and ((bb <= a and cc <= b) or (bb <= b and cc <= a)):
res = max(res, aa + dp(idx+1, bb, cc, aa))
return res
return dp(0, 101, 101, 101)
提交代码评测得到:耗时404ms,占用内存35.4MB。
当前最优的代码实现耗时132ms,大致看了一下,感觉思路上和我们是一致的,不过细节实现上有所差别,感觉比我们的更加简明一些,不过细节没有细看,有兴趣的读者可以自行研究一下。