力扣周赛337题解

47 阅读7分钟

6319. 奇偶位数

题目描述

给定一个整数 n ,返回一个长度为 2 的数组 ans ,其中 ans[0] 表示 n 的二进制表示中奇数位上 1 的个数,ans[1] 表示 n 的二进制表示中偶数位上 1 的个数。

注意:数组下标从 0 开始计数,即最低位为第 0 位。

思路分析

按照题意模拟即可。我们可以用位运算来判断每一位是否为 1 ,并且根据位的奇偶性来更新答案数组。具体地,我们可以从低到高遍历 n 的每一位,用 (n >> i) & 1 来得到第 i 位的值,如果为 1 ,则根据 i & 1 来判断是奇数位还是偶数位,并且对应地增加 ans[0]ans[1] 的值。由于题目保证 n < 2^11 ,所以我们只需要遍历 11 位即可。

代码实现

class Solution:
    def evenOddBit(self, n: int) -> List[int]:
        ans = [0, 0] # 初始化答案数组
        for i in range(11): # 遍历每一位
            if (n >> i) & 1: # 如果第 i 位为 1
                if i & 1: # 如果 i 是奇数
                    ans[0] += 1 # 增加奇数位上 1 的个数
                else: # 如果 i 是偶数
                    ans[1] += 1 # 增加偶数位上 1 的个数
        return ans # 返回答案数组

6322. 检查骑士巡视方案

题目描述

给定一个大小为 n x n 的棋盘和一个二维数组 grid ,其中每个元素表示该位置的步数。如果骑士从 (0, 0) 出发,并且按照步数从小到大的顺序走完所有位置,返回 true ,否则返回 false 。骑士只能按照国际象棋中的规则移动,即每次只能走 “日” 字形。

注意:输入保证步数不重复。

思路分析

输入保证步数不重复,因此直接按步数排序,判断相邻的步数是可以走到的即可。注意要求骑士从 (0, 0) 开始,注意判断。

具体地,我们可以用一个列表 a 来存储所有位置的步数和坐标,然后对 a 按照步数进行排序。然后我们遍历 a 的每一对相邻元素,判断它们是否满足骑士的移动规则,即横坐标之差的绝对值和纵坐标之差的绝对值是否分别为 12 或者 21 。如果有任何一对不满足,就返回 false 。最后,还要检查 a 的第一个元素是否是 (0, 0, 0) ,即起点位置的步数是否为 0 。如果是,就返回 true ,否则返回 false

代码实现

class Solution:
    def checkValidGrid(self, grid: List[List[int]]) -> bool:
        n = len(grid) # 获取棋盘大小
        a = [] # 初始化存储步数和坐标的列表
        for i, row in enumerate(grid): # 遍历每一行
            for j, v in enumerate(row): # 遍历每一列
                a.append((v, i, j)) # 将步数和坐标加入列表
        a.sort() # 按照步数排序

        def ok(x, y, j, k): # 定义一个函数判断两个位置是否满足骑士的移动规则
            if abs(x - j) == 1 and abs(y - k) == 2: # 如果横坐标之差为 1 ,纵坐标之差为 2
                return True # 返回 True
            if abs(x - j) == 2 and abs(y - k) == 1: # 如果横坐标之差为 2 ,纵坐标之差为 1
                return True # 返回 True
            return False # 否则返回 False

        for i in range(1, n * n): # 遍历每一对相邻元素
            (_, x, y), (_, j, k) = a[i - 1], a[i] # 获取它们的步数和坐标
            if not ok(x, y, j, k): # 如果不满足骑士的移动规则
                return False # 返回 False

        return a[0] == (0, 0, 0) # 返回起点位置的步数是否为 0

6352. 美丽子集的数目

题目描述

给定一个长度为 n 的正整数数组 nums 和一个正整数 k ,定义一个子集 s 是美丽的,当且仅当 s 中的任意两个元素都满足它们的差不等于 k 。返回数组 nums 中所有美丽子集的数目。由于答案可能很大,返回它对 10^9 + 7 取模后的结果。

注意:子集可以为空,但不能包含重复元素。

思路分析

这是一道深度优先搜索(DFS)的题目。我们可以从小到大遍历数组中的每个元素,对于每个元素,我们有两种选择:加入当前子集或者不加入。如果加入当前子集,我们需要判断是否会导致子集不美丽,即是否存在与当前元素差为 k 的元素已经在子集中。如果不会,我们就可以继续搜索下一个元素;如果会,我们就需要剪枝,即放弃这个选择。如果不加入当前子集,我们也可以继续搜索下一个元素。当我们遍历完所有元素后,我们就得到了一个美丽子集,可以将答案加一。

为了方便判断是否存在与当前元素差为 k 的元素已经在子集中,我们可以用一个哈希表来记录子集中的每个元素出现的次数。每当我们加入一个元素时,就将其在哈希表中的值加一;每当我们移除一个元素时,就将其在哈希表中的值减一。这样,我们只需要查询哈希表中是否存在 nums[i] - k 或者 nums[i] + k 的键即可。

另外,为了避免重复计算相同的子集,我们可以先对数组进行排序,然后保证每次搜索时只考虑当前元素及其之后的元素。

代码实现

class Solution:
    def beautifulSubsets(self, nums: List[int], k: int) -> int:
        nums.sort() # 对数组进行排序
        n = len(nums) # 获取数组长度
        ans = 0 # 初始化答案
        s = Counter() # 初始化哈希表

        def dfs(i): # 定义一个深度优先搜索的函数
            nonlocal ans # 声明答案为非局部变量
            if i == n: # 如果遍历完所有元素
                ans += 1 # 将答案加一
                return # 返回
            v = nums[i] # 获取当前元素
            if s[v - k] == 0 and s[v + k] == 0: # 如果不存在与当前元素差为 k 的元素已经在子集中
                s[v] += 1 # 将当前元素加入哈希表
                dfs(i + 1) # 搜索下一个元素
                s[v] -= 1 # 将当前元素移除哈希表
            dfs(i + 1) # 不加入当前元素,搜索下一个元素

        dfs(0) # 从第一个元素开始搜索
        return (ans - 1) % (10**9 + 7) # 返回答案对 10^9 + 7 取模后的结果,减一是因为空集不算美丽子集

6321. 执行操作后的最大 MEX

题目描述

给定一个长度为 n 的正整数数组 nums 和一个正整数 value ,定义一个操作如下:从数组中任意选择一个元素,将其加上或减去 value 。你可以执行任意次数的操作,返回执行操作后的数组中的最大 MEX 值。MEX 值是指从 0 开始,第一个不存在于数组中的正整数。

思路分析

在可以任意次数加减 value 的情况下,每个数 x 都可以变成 x + y * value ,其中 y 是任意整数,value 相当于一个模数。那么从 0 开始向大遍历,看看这个数能否从已知里来,显然需要同余的数里来。把所有同余的数计数到一起即可。

具体地,我们可以用一个哈希表来记录数组中每个元素对 value 取模后的出现次数。然后我们从 0 开始遍历每个正整数,如果它对 value 取模后在哈希表中有对应的值,说明它可以由数组中的某个元素经过操作得到,那么我们就将哈希表中的值减一,并且继续遍历下一个正整数。如果它对 value 取模后在哈希表中没有对应的值,说明它不能由数组中的任何元素经过操作得到,那么我们就找到了最大 MEX 值,返回即可。

代码实现

class Solution:
    def findSmallestInteger(self, nums: List[int], value: int) -> int:
        n = len(nums) # 获取数组长度
        cnt = Counter() # 初始化哈希表
        for v in nums: # 遍历每个元素
            cnt[v % value] += 1 # 将其对 value 取模后加入哈希表
        ans = 0 # 初始化答案
        while cnt[ans % value] > 0: # 如果当前正整数对 value 取模后在哈希表中有对应的值
            cnt[ans % value] -= 1 # 将哈希表中的值减一
            ans += 1 # 将答案加一
        return ans # 返回答案