LeetCode 题解工作台
价值和小于等于 K 的最大数字
给你一个整数 k 和一个整数 x 。整数 num 的价值是它的二进制表示中在 x , 2x , 3x 等位置处 设置位 的数目(从最低有效位开始)。下面的表格包含了如何计算价值的例子。 x num Binary Representation Price 1 13 0 0 0 0 0 1 1 0 1 …
3
题型
5
代码语言
3
相关题
当前训练重点
中等 · 状态·转移·动态规划
答案摘要
我们注意到,如果 增大,数字 到 的总价值也会增大。因此,我们可以使用二分查找的方法找到最大的廉价数字。 我们定义二分查找的左边界 $l = 1$,由于每 $2^x + 1$ 个数中至少有一个数字是有价值的,而总价值不超过 ,因此我们可以设定二分查找的右边界 $r = 10^{18}$。
Interview AiBoxInterview AiBox 实时 AI 助手,陪你讲清 状态·转移·动态规划 题型思路
题目描述
给你一个整数 k 和一个整数 x 。整数 num 的价值是它的二进制表示中在 x,2x,3x 等位置处 设置位 的数目(从最低有效位开始)。下面的表格包含了如何计算价值的例子。
| x | num | Binary Representation | Price |
|---|---|---|---|
| 1 | 13 | 000001101 | 3 |
| 2 | 13 | 000001101 | 1 |
| 2 | 233 | 011101001 | 3 |
| 3 | 13 | 000001101 | 1 |
| 3 | 362 | 101101010 | 2 |
num 的 累加价值 是从 1 到 num 的数字的 总 价值。如果 num 的累加价值小于或等于 k 则被认为是 廉价 的。
请你返回 最大 的廉价数字。
示例 1:
输入:k = 9, x = 1 输出:6 解释:由下表所示,6 是最大的廉价数字。
| x | num | Binary Representation | Price | Accumulated Price |
|---|---|---|---|---|
| 1 | 1 | 001 | 1 | 1 |
| 1 | 2 | 010 | 1 | 2 |
| 1 | 3 | 011 | 2 | 4 |
| 1 | 4 | 100 | 1 | 5 |
| 1 | 5 | 101 | 2 | 7 |
| 1 | 6 | 110 | 2 | 9 |
| 1 | 7 | 111 | 3 | 12 |
示例 2:
输入:k = 7, x = 2 输出:9 解释:由下表所示,9 是最大的廉价数字。
| x | num | Binary Representation | Price | Accumulated Price |
|---|---|---|---|---|
| 2 | 1 | 0001 | 0 | 0 |
| 2 | 2 | 0010 | 1 | 1 |
| 2 | 3 | 0011 | 1 | 2 |
| 2 | 4 | 0100 | 0 | 2 |
| 2 | 5 | 0101 | 0 | 2 |
| 2 | 6 | 0110 | 1 | 3 |
| 2 | 7 | 0111 | 1 | 4 |
| 2 | 8 | 1000 | 1 | 5 |
| 2 | 9 | 1001 | 1 | 6 |
| 2 | 10 | 1010 | 2 | 8 |
提示:
1 <= k <= 10151 <= x <= 8
解题思路
方法一:二分查找 + 数位 DP
我们注意到,如果 增大,数字 到 的总价值也会增大。因此,我们可以使用二分查找的方法找到最大的廉价数字。
我们定义二分查找的左边界 ,由于每 个数中至少有一个数字是有价值的,而总价值不超过 ,因此我们可以设定二分查找的右边界 。
接下来,我们进行二分查找,对于每一个 ,我们使用数位 DP 的方法计算出 到 的总价值,如果总价值不超过 ,则说明 是一个廉价数字,我们将左边界 更新为 ,否则我们将右边界 更新为 。
最后,我们返回左边界 即可。
时间复杂度 ,空间复杂度 。
class Solution:
def findMaximumNumber(self, k: int, x: int) -> int:
@cache
def dfs(pos, limit, cnt):
if pos == 0:
return cnt
ans = 0
up = (self.num >> (pos - 1) & 1) if limit else 1
for i in range(up + 1):
ans += dfs(pos - 1, limit and i == up, cnt + (i == 1 and pos % x == 0))
return ans
l, r = 1, 10**18
while l < r:
mid = (l + r + 1) >> 1
self.num = mid
v = dfs(mid.bit_length(), True, 0)
dfs.cache_clear()
if v <= k:
l = mid
else:
r = mid - 1
return l
复杂度分析
| 指标 | 值 |
|---|---|
| 时间 | Depends on the final approach |
| 空间 | Depends on the final approach |
面试官常问的追问
外企场景- question_mark
Understanding the trade-offs between binary search and dynamic programming for optimization.
- question_mark
Ability to apply bit manipulation in a dynamic programming context.
- question_mark
Familiarity with binary search as a method to limit the range of potential solutions.
常见陷阱
外企场景- error
Overcomplicating the bit manipulation logic for price calculations.
- error
Failing to optimize the search by using binary search efficiently.
- error
Not handling edge cases, such as when k is very small or very large.
进阶变体
外企场景- arrow_right_alt
Adjusting the price calculation for different bit positions.
- arrow_right_alt
Optimizing the approach for varying sizes of k and x.
- arrow_right_alt
Applying this method in problems with different price calculation rules.