2024.3.19力扣(1200-1400)刷题记录

本文介绍了四个LeetCode题目及其解决方案,涉及模拟、排序、哈希表、双指针(滑动窗口)等技术,展示了在处理数组问题时的不同策略和优化方法。
摘要由CSDN通过智能技术生成

一、3038. 相同分数的最大操作数目 I

模拟

当n==0或1时,不用判断。n-(n&1)的目的是为了区分奇偶数,奇数减一,偶数不变。并且当n==2时,range(2,2,2)为空,index不会超。运用变量存储前两个元素的和,避免多次求和运算。代码如下:

class Solution:
    def maxOperations(self, nums: List[int]) -> int:
        # 模拟
        n = len(nums)
        cnt = 1
        target = nums[0] + nums[1]
        for i in range(2,n-(n&1),2):
            # if nums[i] + nums[i+1] != nums[0] + nums[1]:
            if nums[i] + nums[i+1] != target:
                break
            cnt += 1
        return cnt

二、2148. 元素计数

1.排序。当然其实排序可能用处不是很大,后面统计个数还是要遍历。

class Solution:
    def countElements(self, nums: List[int]) -> int:
        # 满足条件的元素个数即为除去最小值和最大值的元素的数目
        # 值得注意的是,最大值和最小值可能有多个
        # 排序
        n = len(nums)
        nums.sort()
        if nums[0] == nums[n-1]:
            return 0
        return n - nums.count(nums[0]) - nums.count(nums[n-1])

2.遍历+函数。下面为简便写法,但是相当于两次遍历。代码如下:

class Solution:
    def countElements(self, nums: List[int]) -> int:
        # 满足条件的元素个数即为除去最小值和最大值的元素的数目
        # 值得注意的是,最大值和最小值可能有多个
        # 遍历
        min_,max_ = min(nums),max(nums)
        if min_ == max_:
            return 0
        return len(nums) - nums.count(min_) - nums.count(max_)

3.一次遍历。之前有想到边求最大小值边计数,但是由于最大小值数值在变,就放弃了,没有想到可以在最大小值发生改变时,同时将个数清为1。方法参考灵神题解(. - 力扣(LeetCode)),代码如下:

class Solution:
    def countElements(self, nums: List[int]) -> int:
        # 满足条件的元素个数即为除去最小值和最大值的元素的数目
        # 值得注意的是,最大值和最小值可能有多个
        # 一次遍历
        min_,cntmin,max_,cntmax = inf,0,-inf,0
        for x in nums:
            if x > max_:
                max_,cntmax = x,1
            elif x == max_:
                cntmax += 1
            if x < min_:
                min_,cntmin = x,1
            elif x == min_:
                cntmin += 1
        if min_ == max_:
            return 0
        return len(nums) - cntmax - cntmin

 三、2367. 算术三元组的数目

1.遍历,时复O(n^3)。

class Solution:
    def arithmeticTriplets(self, nums: List[int], diff: int) -> int:
        # 严格递增,无重复数字,寻找范围在[i+1,i+diff]闭区间
        # 注意右端点别出界
        # 遍历 时复O(n^3)
        n = len(nums)
        ans = 0
        for i in range(n-2):
            for j in range(i+1,min(i+diff+1,n-1)):
                if nums[j] - nums[i] > diff:    #后面不会再有,跳出循环
                    break
                elif nums[j] - nums[i] == diff:
                    for k in range(j+1,min(j+diff+1,n)):
                        if nums[k] - nums[j] > diff:
                            break
                        elif nums[k] - nums[j] == diff:
                            ans += 1
        return ans

2.哈希表,时复O(n)。方法来自灵神题解(. - 力扣(LeetCode))。代码如下:

class Solution:
    def arithmeticTriplets(self, nums: List[int], diff: int) -> int:
        # 哈希表 时复O(n)
        # 等差三元组
        s = set(nums)
        return sum(x - diff in s and x + diff in s for x in nums)

优化,来自灵神题解。代码如下:

class Solution:
    def arithmeticTriplets(self, nums: List[int], diff: int) -> int:
        # 哈希表优化
        # 数组严格递增 i,j一定在k前面
        ans,s = 0,set()
        for x in nums:
            if x - diff in s and x - 2*diff in s:
                ans += 1
            s.add(x)
        return ans

3.同向双指针(滑动窗口),时复O(n)。有想到使用滑动窗口,但是没写出来。方法来自灵神题解。代码如下:

class Solution:
    def arithmeticTriplets(self, nums: List[int], diff: int) -> int:
        # 同向双指针(滑动窗口)
        ans,i,j = 0,0,1
        for x in nums:
            while nums[j] + diff < x:
                #j一定小于k,等于时上式>=
                j += 1
            if nums[j] + diff > x:
                continue
            # nums[j] + diff == x
            while nums[i] + diff < nums[j]:
                i += 1
            if nums[i] + diff == nums[j]:
                ans += 1
        return ans

 四、1688. 比赛中的配对次数

1.模拟

class Solution:
    def numberOfMatches(self, n: int) -> int:
        # 模拟
        ans = 0
        while n > 1:
            flag = n&1
            ans += (n - flag) // 2 
            n = (n - flag) // 2 + flag
        return ans

2.数学(真服了哈哈哈哈,还真没想到)。方法来自宫水三叶题解(. - 力扣(LeetCode))。代码如下:

class Solution:
    def numberOfMatches(self, n: int) -> int:
        # 数学
        # n个队伍淘汰n-1个,每次配对淘汰一个,一共n-1次
        return n-1

宫水三叶题解中的引申题目练习:

(1)题目:747. 至少是其他数字两倍的最大数

解题:

遍历

class Solution:
    def dominantIndex(self, nums: List[int]) -> int:
        # 遍历
        # 找出最大值和次大值
        # 如果最大值是次大值的两倍则其他满足条件
        a,b = -1,-1     #最大,次大
        idx = 0
        for i,x in enumerate(nums):
            if x > a:
                a,b = x,a
                idx = i
            elif x > b:
                b = x
        return idx if a >= b*2 else -1

(2)题目:1716. 计算力扣银行的钱

解题:

数学

class Solution:
    def totalMoney(self, n: int) -> int:
        # 第i周 i ... i+6(整周)
        # 和为 7i+21
        # 然后j周又求和,再加上多余的天数(i==j)
        # 7*(1+2+...+j) + 21*j
        # 剩余的天数 j+1 ... j+n%7
        j = n // 7
        # return (j + 1)*j // 2 * 7 + j*21 + sum(range(j+1,j+n%7+1))
        mod = n%7
        return (j + 1)*j // 2 * 7 + j*21 + (2*j+mod+1)*mod // 2

感谢你看到这里!一起加油吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值