需要多掌握解题套路
比赛地址
100157. 大于等于顺序前缀和的最小缺失整数
class Solution:
def missingInteger(self, nums: List[int]) -> int:
# Step 1: Find the longest consecutive prefix
i = 0
for i in range(1, len(nums)):
if nums[i] != nums[i - 1] + 1:
break
else:
# Handle the case where the entire array is a consecutive prefix
i += 1
# Step 2: Calculate the sum of the longest consecutive prefix
prefix_sum = sum(nums[:i])
# Step 3: Find the smallest missing integer greater than the prefix sum
missing = prefix_sum
while missing in nums:
missing += 1
return missing
100168. 使数组异或和等于 K 的最少操作次数
class Solution:
def minOperations(self, nums: List[int], k: int) -> int:
# Step 1: Calculate the XOR of all elements in nums
m = 0
for num in nums:
m ^= num
# Step 2: Count the number of different bits between m and k
xor = m ^ k
count = 0
while xor:
count += xor & 1
xor >>= 1
return count
100159. 使 X 和 Y 相等的最少操作次数
class Solution:
def minimumOperationsToMakeEqual(self, x: int, y: int) -> int:
# Queue will contain pairs (current_value, operations_count)
queue = deque([(x, 0)])
visited = set() # To keep track of already visited values
while queue:
current, operations = queue.popleft()
# If we have reached the target, return the number of operations
if current == y:
return operations
# Ensure we do not visit the same number again
if current in visited:
continue
visited.add(current)
# If current is divisible by 11, enqueue the divided result
if current % 11 == 0:
queue.append((current // 11, operations + 1))
# If current is divisible by 5, enqueue the divided result
if current % 5 == 0:
queue.append((current // 5, operations + 1))
# Always enqueue the results of adding or subtracting 1
queue.append((current + 1, operations + 1))
queue.append((current - 1, operations + 1))
# If y is never reached, return -1 or some error value
return -1
100163. 统计强大整数的数目
函数
numberOfPowerfulInt
:
- 输入参数:整数
start
,finish
,limit
和字符串s
。- 返回值:区间
[start, finish]
内符合条件的数字数量。- 实现:调用
dfs
函数两次来计算不超过finish
和start - 1
的符合条件的数字数量,然后相减得到结果。数位 DP 函数
dfs
:
- 输入参数:当前处理的数位索引
i
,一个布尔值is_limit
表示当前是否受到上界t
的限制,以及当前考虑的数的字符串表示t
。- 返回值:在给定限制下,从当前位开始能构造出的符合条件的数字数量。
- 实现:
- 首先检查边界条件,当剩下的位数等于
s
的长度时,只能填入s
,并根据是否受限制判断是否可行。- 对于每一位,根据是否受限制和
limit
的值确定当前位的可能数字范围。- 递归地调用
dfs
来处理下一位,并累计所有可能性的总数。递归和缓存:
dfs
函数使用递归来处理每一位,通过@cache
装饰器对函数结果进行缓存,以避免重复计算相同状态的结果,从而提高性能。
总体而言,这个实现通过精确地处理每一位的可能性,并利用递归和函数缓存来有效地处理大范围的数据。这种方法在处理复杂的数位相关问题时非常有效,尤其是在涉及大数字时。
class Solution:
def numberOfPowerfulInt(self, start: int, finish: int, limit: int, s: str) -> int:
n = len(s)
# 数位dp函数,使用缓存装饰器以优化性能
@cache
def dfs(i, is_limit, t):
# 如果剩余数字的长度小于后缀s的长度,则不可能构成有效数字
if len(t) < n:
return 0
# 当剩余的位数等于后缀s的长度,只能填入s
if len(t) - i == n:
# 如果当前是受限状态,则检查t的剩余部分是否大于等于s
if is_limit:
return int(s <= t[i:])
else:
# 如果不受限,只有一种情况,即填入s
return 1
res = 0
start = 0
# 如果当前受限,则枚举的数字不能超过t的当前位数字
if is_limit:
end = int(t[i])
else:
end = 9
# 枚举的数字还需受限于limit
end = min(end, limit)
# 枚举当前位可能的数字,并递归处理下一位
for num in range(start, end+1):
res += dfs(i+1, is_limit and num == int(t[i]), t)
return res
# 计算区间[start, finish]内符合条件的数字数量
return dfs(0, True, str(finish)) - dfs(0, True, str(start-1))
is_limit and num == int(t[i])
:这个表达式决定了在下一次递归调用中,是否仍然受到上界t
的限制。
- 如果当前位
num
等于t
在位置i
的数字,并且之前的位置已经受到限制(is_limit
为True
),那么在下一位上仍然受到限制。- 如果
num
不等于t[i]
或之前的位置没有受到限制,那么在下一位上不再受到限制。
下面举例说明这个过程:
假设我们有 t = "5432"
,limit = 9
,并且当前我们在第二位(假设索引从 0 开始),即 i = 1
,之前的数位值是 5
,与 t[0]
相等,所以到目前为止我们是受限的(is_limit = True
)。现在我们要决定第二位 i = 1
的值。
如果我们选择
num = 4
(即等于t[1]
):
- 在下一次递归调用中,我们仍然受限于
t
,因为到目前为止构造出的数字仍然与t
的前缀相匹配。所以,is_limit
仍然为True
。如果我们选择
num = 3
(即小于t[1]
):
- 在这种情况下,我们已经偏离了
t
的对应位置。即使之前是受限的,现在我们可以认为后续的数位不再受到t
的限制。因此,在下一次递归调用中,is_limit
将变为False
。- 这意味着对于这个位置及后续位置上的数位,我们可以自由地选择任何不超过
limit
的数字,而不用担心超过t
。num > t[i]
的情况不会发生,在之前的判断中已经被排除了# 如果当前受限制(is_limit),则枚举的数字不能超过t的当前位数字 if is_limit: end = int(t[i]) else: end = 9