LeetCode笔记:Weekly Contest 337

文章详细记录了LeetCode周赛337中的四道题目的解题思路,包括Python代码实现,并重点讨论了第三题的算法优化,通过调整状态表示和使用缓存显著提高了运行效率。

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

1. 题目一

给出题目一的试题链接如下:

1. 解题思路

这一题就是按照题意看一下所有二进制中1出现的位置的奇偶性然后进行一下统计即可。

2. 代码实现

给出python代码实现如下:

class Solution:
    def evenOddBit(self, n: int) -> List[int]:
        d = bin(n)[2:]
        even, odd = 0, 0
        for i, ch in enumerate(d[::-1]):
            if ch == "0":
                continue
            if i % 2 == 0:
                even += 1
            else:
                odd += 1
        return [even, odd]

提交代码评测得到:耗时36ms,占用内存13.8MB。

2. 题目二

给出题目二的试题链接如下:

1. 解题思路

这一题我的思路就是首先将棋盘上的所有位置按照给定的行进路线进行排序,然后看一下每一步是否可以走到即可。

2. 代码实现

给出python代码实现如下:

class Solution:
    def checkValidGrid(self, grid: List[List[int]]) -> bool:
        if grid[0][0] != 0:
            return False
        
        n = len(grid)
        steps = sorted([(grid[i][j], i, j) for i in range(n) for j in range(n)])
        
        def is_reachable(s1, s2):
            return abs(s1[1] - s2[1]) * abs(s1[2] - s2[2]) == 2 and s2[0]-s1[0] == 1
        
        n = len(steps)
        return all(is_reachable(steps[i], steps[i+1]) for i in range(n-1))

提交代码评测得到:耗时73ms,占用内存13.9MB。

3. 题目三

给出题目三的试题链接如下:

1. 解题思路

这一题我们一开始的思路就是一个迭代的思路,每次考察每一个数是否是否要选择,然后如果选择的话就banned掉那些不能再被选择的数,然后考察结果即可。

2. 代码实现

给出python代码实现如下:

class Solution:
    def beautifulSubsets(self, nums: List[int], k: int) -> int:
        cnt = Counter(nums)
        nums = sorted(cnt.keys())
        indices = {x: i for i, x in enumerate(nums)}
            
        n = len(nums)
        
        def dfs(idx, s):
            if idx == n:
                return 1 if s != 0 else 0
            
            res = dfs(idx+1, s)
            if (1 << idx) & s == 0:
                s = s | (1 << idx)
                if nums[idx] + k in indices:
                    s = s | (1 << indices[nums[idx] + k])
                res += (2**cnt[nums[idx]]-1) * dfs(idx+1, s)
            return res
        
        return dfs(0, 0)

提交代码评测得到:耗时4614ms,占用内存14.1MB。

不过这个算法耗时非常的久,且即使使用缓存进行优化,也无法进行加速,因为状态s事实上几乎不会出现重复,因此无法重复利用计算结果。

而我们看了一下当前最快的算法,耗时几乎少了两个量级。因此,我们想要看一下他们的算法,然后对我们的算法进行一下加速。

3. 算法优化

看了一下他们的算法之后,发现算法思路上其实差不多,唯一的区别在于,他们给出的状态s并不包含当前的取用状态,而只表示禁用元素位置,从而就会有很多重复计算,因此我们就可以使用缓存来进行算法加速了。

给出python代码实现如下:

class Solution:
    def beautifulSubsets(self, nums: List[int], k: int) -> int:
        n = len(nums)
        banned = [0 for _ in range(n)]
        for i in range(n):
            for j in range(n):
                if abs(nums[i]-nums[j]) == k:
                    banned[i] = banned[i] | (1<<j)
        
        @lru_cache(None)
        def dfs(idx, s):
            if idx == n:
                return 1
            res = dfs(idx+1, s)
            if (1<<idx) & s == 0:
                res += dfs(idx+1, s | banned[idx])
            return res
        
        return dfs(0, 0) - 1

提交代码评测得到:耗时90ms,占用内存22.4MB。

4. 题目四

给出题目四的试题链接如下:

1. 解题思路

这一题其实相较于上一题反而简单的不行。

要找到经过若干次操作之后得到的最大的无法覆盖的最小整数,我们只需要对所有的数字对value进行同余统计,假设余数r的数共有k个,那么第一个无法被覆盖的数字必然不大于 v ∗ k + r v*k+r vk+r

因此,我们只需要按照余数进行统计,然后找到次数最小的那个r值进行计算即可。

2. 代码实现

给出python代码实现如下:

class Solution:
    def findSmallestInteger(self, nums: List[int], value: int) -> int:
        cnt = [0 for _ in range(value)]
        for x in nums:
            cnt[x % value] += 1
        k = min(cnt)
        for i, x in enumerate(cnt):
            if x == k:
                return k * value + i
        return -1

提交代码评测得到:耗时839ms,占用内存28.9MB。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值