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 v∗k+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。