题目一:
题目链接: https://leetcode-cn.com/problems/maximum-score-after-splitting-a-string/
解题思路:
右边的为1的个数,先遍历一次,计算有多少个1
添加三个变量,left为左半部分0的个数,初始化为0;right为右半部分1的个数,初始化为上一步的统计值;max_sum为当前left + right的最大值
然后再次遍历字符串,如果是0,则left += 1;如果是1,则right -= 1;更新max_sum = max(max_sum, left + right)
代码实现:
class Solution:
def maxScore(self, s: str) -> int:
rec = collections.Counter(s)
left = 0
right = rec['1']
res = 0
for mid in range(len(s) - 1):
c = s[mid]
if c == '0':
left += 1
else:
right -= 1
res = max(res, left + right)
return res
题目二:
题目链接: https://leetcode-cn.com/problems/maximum-points-you-can-obtain-from-cards/
解题思路:
假设一共有n个数字;每次从左右各取一个数字,取k个数字的最大和,可以转换为连续子序列为n - k个数字的最小和问题
求出n - k个元素的连续子序列最小和,然后用总和减去最小和,就是最大和
代码实现:
class Solution:
def maxScore(self, cardPoints: List[int], k: int) -> int:
tmp_len = len(cardPoints) - k
total_sum = 0
min_sum = float('inf')
left = 0
curr_sum = 0
for idx, num in enumerate(cardPoints):
total_sum += num
if idx - left + 1 <= tmp_len:
curr_sum += num
continue
min_sum = min(min_sum, curr_sum, curr_sum - cardPoints[left] + num)
curr_sum = curr_sum - cardPoints[left] + num
left += 1
return total_sum - min_sum
题目三:
题目链接: https://leetcode-cn.com/problems/diagonal-traverse-ii/
解题思路:
假设每一个对角线为一层,即对于第一个nums = [[1, 2, 3], [4, 5, 6], [7, 8, 9]],每个对角线分层的结果为:
第一层 = [1]
第二层 = [4, 2]
第三层 = [7, 5, 3]
第四层 = [8, 6]
第五层 = [9]
如果按照这个顺序拼接好,然后按照层的顺序将数组拼接,就是最终结果
假设一个数字的下标为nums[i][j],可以看出下记对应关系:
第0层 : (0,0)
第1层 :(1,0), (0,1)
第2层 : (2,0), (1,1), (0,2)
.....
第n层 :(n,0), (n - 1, 1), (n - 2, 2), ..., (0, n)
可以看出,i + j就是所在的层
代码实现:
class Solution:
def findDiagonalOrder(self, nums: List[List[int]]) -> List[int]:
rec = collections.defaultdict(list)
for i in range(len(nums)):
for j in range(len(nums[i])):
curr_key = i + j
rec[curr_key].append(nums[i][j])
res = []
for key in sorted(rec.keys()):
# 因为是按行遍历的,所以这里需要反转一下,才是题目要求的顺序
res += reversed(rec[key])
return res
题目四:
题目链接: https://leetcode-cn.com/problems/constrained-subset-sum/
解题思路:
从前向后遍历,遍历的同时添加一个优先队列和当前遍历过的最大值,保存之前每一位的和
在遍历到第 i 位时,当前位置的最大值,是从 i - k 到 i 的最大值 + i 的值
然后更新遍历过的最大值
代码实现:
import queue
class Solution:
def constrainedSubsetSum(self, nums: List[int], k: int) -> int:
max_sum = nums[0]
q = queue.PriorityQueue()
# 因为优先队列的get获取的是最小值,所以这里 * -1,使得最大值变为最小值
# 后续 * -1的处理原因相同
q.put((nums[0] * -1, 0))
for idx in range(1, len(nums)):
while not q.empty():
pre_max, pre_idx = q.get()
if idx - pre_idx > k:
continue
q.put((pre_max, pre_idx))
curr_max = max(pre_max * -1 + nums[idx], nums[idx])
max_sum = max(max_sum, curr_max)
q.put((curr_max * -1, idx))
break
return max_sum
后记:
这次周赛总体来说挺简单的
但是最后一题还是在时限内没有提交成功;开始没想到使用优先队列,都是用dp数组保存每一位的最大值
然后从第i位向前遍历k个数字找最大值。结果一直超时
直到比赛完吃饭时候才想到用优先队列来保存,修改后一次提交成功。与本次第一名的差距为:
也就是第一名已经做完最后一题了,我第二题还没做完
回想昨天的团队赛周赛,第一题看了1个多小时没想出来具体公式怎么计算,结果首次参加竞赛,但是却没成功提交一道题
需要学习的东西还有很多啊,菜鸡一个=,=