LeetCode笔记:Weekly Contest 233 比赛记录

本文记录了一次LeetCode周赛的参赛体验,分享了解题思路和Python代码实现,涉及最大升序子数组和、积压订单中的订单总数、有界数组中指定下标处的最大值等题目,以及对题目理解的难点和解题策略的反思。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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. 解题思路

第二题真心很蠢,就是读题目,又臭又长,关键点其实就以下几点:

  1. orders中的每一个元素(price, amount, orderType)事实上包括amount次操作;
  2. buy的时候比较的是sell队列;sell的时候比较的是buy队列;
  3. 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

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值