LeetCode 题解工作台
大数组元素的乘积
一个非负整数 x 的 强数组 指的是满足元素为 2 的幂且元素总和为 x 的最短有序数组。下表说明了如何确定 强数组 的示例。可以证明, x 对应的强数组是独一无二的。 数字 二进制表示 强数组 1 0000 1 [1] 8 0 1 000 [8] 10 0 1 0 1 0 [2, 8] 13 0 …
3
题型
4
代码语言
3
相关题
当前训练重点
困难 · 二分·搜索·答案·空间
答案摘要
连续的正整数数字对应的强整数数组连接得到数组 ,题目需要我们求出对于每个查询 $[\textit{left}, \textit{right}, \textit{mod}]$,子数组 的乘积对 取模的结果。由于子数组每个元素都是 的幂,这等价于求子数组的幂次之和 ,然后计算 $2^{\textit{power}} \bmod \textit{mod}$。例如,对于子数组 $[1, 4, 8]$…
Interview AiBoxInterview AiBox 实时 AI 助手,陪你讲清 二分·搜索·答案·空间 题型思路
题目描述
一个非负整数 x 的 强数组 指的是满足元素为 2 的幂且元素总和为 x 的最短有序数组。下表说明了如何确定 强数组 的示例。可以证明,x 对应的强数组是独一无二的。
| 数字 | 二进制表示 | 强数组 |
|---|---|---|
| 1 | 00001 | [1] |
| 8 | 01000 | [8] |
| 10 | 01010 | [2, 8] |
| 13 | 01101 | [1, 4, 8] |
| 23 | 10111 | [1, 2, 4, 16] |
我们将每一个升序的正整数 i (即1,2,3等等)的 强数组 连接得到数组 big_nums ,big_nums 开始部分为 [1, 2, 1, 2, 4, 1, 4, 2, 4, 1, 2, 4, 8, ...] 。
给你一个二维整数数组 queries ,其中 queries[i] = [fromi, toi, modi] ,你需要计算 (big_nums[fromi] * big_nums[fromi + 1] * ... * big_nums[toi]) % modi 。
请你返回一个整数数组 answer ,其中 answer[i] 是第 i 个查询的答案。
示例 1:
输入:queries = [[1,3,7]]
输出:[4]
解释:
只有一个查询。
big_nums[1..3] = [2,1,2] 。它们的乘积为 4。结果为 4 % 7 = 4。
示例 2:
输入:queries = [[2,5,3],[7,7,4]]
输出:[2,2]
解释:
有两个查询。
第一个查询:big_nums[2..5] = [1,2,4,1] 。它们的乘积为 8 。结果为 8 % 3 = 2。
第二个查询:big_nums[7] = 2 。结果为 2 % 4 = 2。
提示:
1 <= queries.length <= 500queries[i].length == 30 <= queries[i][0] <= queries[i][1] <= 10151 <= queries[i][2] <= 105
解题思路
方法一:二分查找 + 位运算
连续的正整数数字对应的强整数数组连接得到数组 ,题目需要我们求出对于每个查询 ,子数组 的乘积对 取模的结果。由于子数组每个元素都是 的幂,这等价于求子数组的幂次之和 ,然后计算 。例如,对于子数组 ,即 ,其幂次之和为 ,所以 就是我们要求的结果。
因此,我们不妨将 转换为幂次数组,即对于子数组 ,我们将其转换为 。这样,问题转换为求幂次数组的子数组之和,即 ,其中 表示 的幂次之和,也即是前缀和。
接下来,就是根据下标 计算 的值。我们可以使用二分查找的方法,先找到强数组长度和小于 的最大数字,然后再计算剩下的数字的幂次之和。
我们根据题目描述,列出数字 的强整数:
| 8() | 4() | 2() | () | |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 1 | 0 | 0 | 0 | 1 |
| 2 | 0 | 0 | 1 | 0 |
| 3 | 0 | 0 | 1 | 1 |
| 4 | 0 | 1 | 0 | 0 |
| 5 | 0 | 1 | 0 | 1 |
| 6 | 0 | 1 | 1 | 0 |
| 7 | 0 | 1 | 1 | 1 |
| 8 | 1 | 0 | 0 | 0 |
| 9 | 1 | 0 | 0 | 1 |
| 10 | 1 | 0 | 1 | 0 |
| 11 | 1 | 0 | 1 | 1 |
| 12 | 1 | 1 | 0 | 0 |
| 13 | 1 | 1 | 0 | 1 |
| 14 | 1 | 1 | 1 | 0 |
将数字按照 的区间划分为不同的颜色,可以发现,区间 的数字,相当于在区间 的数字基础上,每个数字加上 。我们可以根据这个规律,计算出 的前 组的所有数字的强数组个数之和 和幂次之和 。
接下来,对于任何数字,我们考虑如何计算其强数组的个数和幂次之和。我们可以通过二进制的方式,从最高位开始,诸位计算。例如,对于数字 ,前 个数字的结果可以由 和 计算得到,而剩下的 的结果,相当于给 的所有数字,即 的所有数字的强数组增加 ,问题转换为计算 的所有数字的强数组的个数和幂次之和。这样,我们可以计算出任意数字的强数组的个数和幂次之和。
最后,我们可以根据 的值,利用快速幂的方法,计算出 的结果。
时间复杂度 ,空间复杂度 。其中 为查询的个数,而 为数字的上界,本题中 。
m = 50
cnt = [0] * (m + 1)
s = [0] * (m + 1)
p = 1
for i in range(1, m + 1):
cnt[i] = cnt[i - 1] * 2 + p
s[i] = s[i - 1] * 2 + p * (i - 1)
p *= 2
def num_idx_and_sum(x: int) -> tuple:
idx = 0
total_sum = 0
while x:
i = x.bit_length() - 1
idx += cnt[i]
total_sum += s[i]
x -= 1 << i
total_sum += (x + 1) * i
idx += x + 1
return (idx, total_sum)
def f(i: int) -> int:
l, r = 0, 1 << m
while l < r:
mid = (l + r + 1) >> 1
idx, _ = num_idx_and_sum(mid)
if idx < i:
l = mid
else:
r = mid - 1
total_sum = 0
idx, total_sum = num_idx_and_sum(l)
i -= idx
x = l + 1
for _ in range(i):
y = x & -x
total_sum += y.bit_length() - 1
x -= y
return total_sum
class Solution:
def findProductsOfElements(self, queries: List[List[int]]) -> List[int]:
return [pow(2, f(right + 1) - f(left), mod) for left, right, mod in queries]
复杂度分析
| 指标 | 值 |
|---|---|
| 时间 | complexity depends on the number of queries and the bit-length of numbers, typically O(queries * log(max_index) * log(max_bit)), while space complexity is O(log(max_index) * log(max_bit)) for precomputed counts. |
| 空间 | Depends on the final approach |
面试官常问的追问
外企场景- question_mark
Look for an approach that avoids building the entire big_nums array explicitly.
- question_mark
Check if the candidate can compute bit contributions using O(log n) methods.
- question_mark
Verify understanding of modular arithmetic on large products.
常见陷阱
外企场景- error
Attempting to generate big_nums entirely leads to memory overflow.
- error
Failing to compute bit contributions correctly for large indices.
- error
Ignoring modular reduction during intermediate multiplication causes overflow.
进阶变体
外企场景- arrow_right_alt
Compute sums instead of products for big_nums subarrays using the same binary search strategy.
- arrow_right_alt
Handle queries where elements are filtered by additional conditions on powers of two.
- arrow_right_alt
Apply the same binary search over valid answer space for ranges in 2D matrices built from powerful arrays.