1. 问题
问题描述(原文):
Given three integers x
, y
, and bound
, return a list of all the powerful integers that have a value less than or equal to bound
.
An integer is powerful if it can be represented as xi + yj
for some integers i >= 0
and j >= 0
.
You may return the answer in any order. In your answer, each value should occur at most once.
Example 1:
Input: x = 2, y = 3, bound = 10
Output: [2,3,4,5,7,9,10]
Explanation:
2 = 20 + 30
3 = 21 + 30
4 = 20 + 31
5 = 21 + 31
7 = 22 + 31
9 = 23 + 30
10 = 20 + 32
Constraints:
- 1 <= x, y <= 100
- 0 <= bound <= 106
2. 分析
看到这题, 思考了几分钟, 只能想到暴力解法, 于是决定先用暴力解法做一下, 提交看看情况.
这是代码:
public List<Integer> powerfulIntegers(int x, int y, int bound) {
Set<Integer> set = new HashSet<>();
for (int j = 0; Math.pow(y, j) < bound; j++) {
for (int i = 0; Math.pow(x, i) + Math.pow(y, j) <= bound; i++) {
set.add((int) (Math.pow(x, i) + Math.pow(y, j)));
if (i > 0 && Math.pow(x, i) == 1) {
break;
}
}
if (j > 0 && Math.pow(y, j) == 1) {
break;
}
}
return new ArrayList<>(set);
}
提交通过测试了, 我惊了==.
通过测试就可以看别人的解法了, 我看了下运行时间短的解法也是暴力求解的(我的暴力是"无脑暴力", 别人的是"优雅暴力"):
public List<Integer> powerfulIntegers2(int x, int y, int bound) {
Set<Integer> result = new HashSet<>();
for (int a = 1; a < bound; a *= x) {
for (int b = 1; a + b <= bound; b *= y) {
result.add(a + b);
if (y == 1) {
break;
}
}
if (x == 1) {
break;
}
}
return new ArrayList<>(result);
}
不过, 同样是暴力, 优雅暴力要比无脑暴力效率高一些.
因为后者:
没有把 i 和 j 显示的写出来, 它把 幂运算 放在每次的迭代中, 这样每次迭代只要做乘法运算即可.
3. 总结
把 幂运算 放在每次的迭代中, 这样可以减少一部分计算量, 数值越大, 效果越明显.
这种优雅暴力解法也不难想到, 解题时应该多注意分析, 无脑暴力求解是下下策, 应该在真的没辙时才使用.