markdown复制## 1. 问题背景与理解
今天遇到一道挺有意思的LeetCode题目(970. Powerful Integers),要求找出所有能表示为x^i + y^j的整数,其中i和j都是非负整数。这种数学与编程结合的题目在实际面试中经常出现,既考察数学思维又检验编码能力。
题目给定三个整数x、y和bound,需要返回所有小于等于bound的powerful integers。比如x=2, y=3, bound=10时,可能的组合包括:
2^0 + 3^1 = 4
2^1 + 3^0 = 3
2^1 + 3^1 = 5
...
最终结果是[2,3,4,5,7,9,10]
> 关键点:需要注意x或y为1时的特殊情况,因为1的任何次方都是1,会导致无限循环
## 2. 算法思路分析
### 2.1 暴力解法可行性
最直观的做法是双层循环枚举所有可能的i和j组合:
```c
for (int i = 0; ; i++) {
for (int j = 0; ; j++) {
int sum = pow(x,i) + pow(y,j);
if (sum > bound) break;
// 记录结果
}
}
但这样会有三个问题:
- 循环终止条件不明确
- 存在重复计算结果
- 对x/y=1的情况处理不当
2.2 数学优化思路
通过数学分析可以发现:
- 当x>1时,x^i的增长是指数级的,i的上限为log_x(bound)
- 同理y>1时,j的上限为log_y(bound)
- 需要用哈希表来去重
3. C语言实现细节
3.1 预处理特殊情况
c复制if (bound < 2) return NULL; // 最小powerful integer是2
if (x == 1 && y == 1) {
if (bound >= 2) {
int* res = malloc(sizeof(int));
res[0] = 2;
*returnSize = 1;
return res;
}
return NULL;
}
3.2 动态计算上限
c复制int x_limit = x == 1 ? 0 : (int)(log(bound) / log(x)) + 1;
int y_limit = y == 1 ? 0 : (int)(log(bound) / log(y)) + 1;
3.3 哈希表实现
由于C没有内置哈希表,可以用uthash库或者简单用大数组:
c复制int hash[bound + 1];
memset(hash, 0, sizeof(hash));
int count = 0;
for (int i = 0; i <= x_limit; i++) {
for (int j = 0; j <= y_limit; j++) {
int sum = (int)(pow(x, i) + pow(y, j));
if (sum <= bound && !hash[sum]) {
hash[sum] = 1;
count++;
}
}
}
4. 完整解决方案
4.1 最终代码结构
c复制int* powerfulIntegers(int x, int y, int bound, int* returnSize) {
*returnSize = 0;
if (bound < 2) return NULL;
// 特殊处理1的幂次
int x_pows[20] = {1}, y_pows[20] = {1};
int x_size = 1, y_size = 1;
if (x != 1) {
while (x_pows[x_size - 1] <= bound) {
x_pows[x_size] = x_pows[x_size - 1] * x;
x_size++;
}
}
// 类似处理y...
// 哈希去重
int hash[bound + 1];
memset(hash, 0, sizeof(hash));
int count = 0;
for (int i = 0; i < x_size; i++) {
for (int j = 0; j < y_size; j++) {
int sum = x_pows[i] + y_pows[j];
if (sum <= bound && !hash[sum]) {
hash[sum] = 1;
count++;
}
}
}
// 构造结果数组...
}
4.2 复杂度分析
- 时间复杂度:O(log_x(bound) * log_y(bound))
- 空间复杂度:O(bound) 用于哈希去重
5. 测试用例与边界情况
5.1 常规测试
c复制x=2, y=3, bound=10 → [2,3,4,5,7,9,10]
x=3, y=5, bound=15 → [2,4,6,8,10,14]
5.2 特殊边界
c复制x=1, y=1, bound=1 → []
x=2, y=1, bound=10 → [2,3,5,9]
bound=0 → []
5.3 大数测试
c复制x=2, y=3, bound=1000000
// 需要验证算法效率
6. 优化与扩展
6.1 性能优化点
- 预计算所有x^i和y^j的值存入数组
- 使用更高效的哈希实现
- 当x或y为1时提前终止内层循环
6.2 类似题目延伸
- 可以尝试解决"Super Ugly Number"问题
- 或者扩展为三个数的powerful integers
实际编码中发现pow()函数有精度问题,改用累乘更可靠。另外LeetCode的C环境需要手动实现哈希,这是比较麻烦的地方。
code复制