【leetcode系列】【算法】第 186 场周赛

题目一:

题目链接: 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个多小时没想出来具体公式怎么计算,结果首次参加竞赛,但是却没成功提交一道题

需要学习的东西还有很多啊,菜鸡一个=,=

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值