0. 赛后总结
这次的比赛简直把我逼疯了,第二题读题目读了n久,完全没感觉题目有任何难度,难度全在读题目上面……
然后第三题,就是一道数学题目加上二分法,然而悲剧的是就是边界条件一直算错,然后就搞得一直到比赛结束都没有提交成功,连带被搞得第四题压根就没有时间去看,简直了……
最后排名果然坑了,前15%都没进,真心坑爹!
唉,果然是太久没有做数学题了,搞得这种简单的计算都能算错,感觉是时候捡起我的吉米多维奇了……
1. 题目一
给出题目一的试题链接如下:
1. 解题思路
第一题没啥好说的,因为是连续的,所以就没啥难度,一轮遍历找到最大的升序子数组即可。
2. 代码实现
给出python代码实现如下:
class Solution:
def maxAscendingSum(self, nums: List[int]) -> int:
n = len(nums)
res = 0
tmp = nums[0]
for i in range(1, n):
if nums[i] > nums[i-1]:
tmp += nums[i]
else:
res = max(res, tmp)
tmp = nums[i]
res = max(res, tmp)
return res
提交代码评测得到:耗时32ms,占用内存14MB。
2. 题目二
给出题目二的试题链接如下:
1. 解题思路
第二题真心很蠢,就是读题目,又臭又长,关键点其实就以下几点:
- orders中的每一个元素
(price, amount, orderType)
事实上包括amount
次操作; buy
的时候比较的是sell
队列;sell
的时候比较的是buy
队列;sell
队列每次取用最小值;buy
队列每次取用最大值。
因此,我们用一个堆排基本就能瞬秒这道题……
2. 代码实现
给出python代码实现如下:
class Solution:
def getNumberOfBacklogOrders(self, orders: List[List[int]]) -> int:
MOD = 10**9+7
sell = []
buy = []
for p, a, o in orders:
if o == 0:
while a != 0 and sell != [] and sell[0][0] <= p:
if sell[0][1] <= a:
a -= sell[0][1]
heapq.heappop(sell)
else:
sell[0][1] -= a
a = 0
if a != 0:
heapq.heappush(buy, [-p, a])
else:
while a != 0 and buy != [] and -buy[0][0] >= p:
if buy[0][1] <= a:
a -= buy[0][1]
heapq.heappop(buy)
else:
buy[0][1] -= a
a = 0
if a != 0:
heapq.heappush(sell, [p, a])
res = sum([x[1] for x in buy]) + sum([x[1] for x in sell])
return res % MOD
提交代码评测得到:耗时732ms,占用内存54.1MB。
3. 题目三
给出题目三的试题链接如下:
1. 解题思路
这一题其实思路非常简单,要使得整体的求和小于目标值,且令给定的index上的数字最大,那么最合适的数字配给方法一定是令index上面的数越大越好,而其他位置上的数越小越好,此时显然有山峰式的数字分布方式能够得到最优解。
而确定了数字的分布之后,那么其实对于任意给定的index上面的数值k,整个数组上所有的数字的总和也就确定了,因此,我们可以使用二分法来最终确定可以取到的最大的k值。
但是,需要注意的是,题目里面要求数字是正整数,所以0是不被允许的,所有的数字需要从1开始计算。
2. 代码实现
给出python代码实现如下:
class Solution:
def maxValue(self, n: int, index: int, maxSum: int) -> int:
def fn(k):
res = k
left = index
if k-left > 0:
res += (k-1+k-left)*left // 2
else:
res += (left-k+1) + k*(k-1) // 2
right = n-1-index
if k-right > 0:
res += (k-1+k-right)*right // 2
else:
res += (right-k+1) + k*(k-1) // 2
return res
l, r = 1, maxSum+1
while l < r-1:
m = (l+r) // 2
s = fn(m)
if s == maxSum:
return m
elif s < maxSum:
l = m
else:
r = m
return l
提交代码评测得到:耗时32ms,占用内存14.2MB。
4. 题目四
给出题目四的试题链接如下:
1. 解题思路
这一题比赛的时候算是完全没有时间看题目吧,赛后看了一下,感觉还是没啥思路,然后看了一下别人的解答,才蓦然发现就是一道trie树的变种题目。
无非就是根据digit构建一个trie树,然后对trie树进行遍历,找到小于等于high的数目的个数以及大于等于low的数目的个数,然后求一个交集就是目标范围内的数字的个数了。
有关trie树的内容可以参考我之前的博客:
2. 代码实现
给出python代码实现如下:
class Trie:
def __init__(self):
self.trie = {}
def add(self, digits):
trie = self.trie
for c in digits:
if c not in trie:
trie[c] = [0, {}]
trie[c][0] += 1
trie = trie[c][1]
if "eos" not in trie:
trie["eos"] = 1
else:
trie["eos"] += 1
return
def find_low(self, digits, tgt):
trie = self.trie
res = 0
for d1, d2 in zip(digits, tgt):
t = d1 ^ d2
if d2 == 0:
if t not in trie:
break
_, trie = trie[t]
else:
res += trie.get(1-t, [0, {}])[0]
_, trie = trie.get(t, [0, {}])
res += trie.get("eos", 0)
return res
def find_high(self, digits, tgt):
trie = self.trie
res = 0
for d1, d2 in zip(digits, tgt):
t = d1 ^ d2
if d2 == 1:
if t not in trie:
break
_, trie = trie[t]
else:
res += trie.get(1-t, [0, {}])[0]
_, trie = trie.get(t, [0, {}])
res += trie.get("eos", 0)
return res
def find(self, digits, low, high):
trie = self.trie
l = self.find_low(digits, high)
h = self.find_high(digits, low)
tot = self.trie.get(0, [0, {}])[0] + self.trie.get(1, [0, {}])[0]
return max(l+h-tot, 0)
class Solution:
def countPairs(self, nums: List[int], low: int, high: int) -> int:
def num2digit(n):
digits = []
for i in range(16):
digits.insert(0, n % 2)
n = n // 2
return digits
low = num2digit(low)
high = num2digit(high)
trie = Trie()
res = 0
for x in nums:
x = num2digit(x)
res += trie.find(x, low, high)
trie.add(x)
return res
提交代码评测得到:耗时4812ms,占用内存28.5MB。
我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=xnvcq8f7c8et