Powerful Integers: A Brute Force Optimization Lesson
Powerful Integers: A Brute Force Optimization Lesson
Given two non-negative integers x and y, an integer is powerful if it equals x^i + y^j for some integers i ≥ 0 and j ≥ 0.
The task: return all powerful integers with values ≤ bound. Each value appears once.
First Approach
I computed all powers of x and y under bound ahead of time. Then I iterated through sums, checking if (sum - x_power) existed in the y_powers table.
class Solution {
public:
vector<int> powerfulIntegers(int x, int y, int bound) {
vector<int> res;
if (bound < 2) {
return res;
}
res.push_back(2);
if (bound < x || bound <y) {
return res;
}
vector<int> xs;
xs.push_back(1);
if (x > 1) {
int p = x;
while(p<bound) {
xs.push_back(p);
p*=x;
}
}
set<int> ys;
ys.insert(1);
if (y > 1) {
int p = y;
while(p<bound) {
ys.insert(p);
p*=y;
}
}
for(int b=3;b<=bound;b++) {
for(int j=0;j<xs.size();j++) {
if (xs[j] >= b) {
break;
}
if (ys.find(b-xs[j]) != ys.end()) {
res.push_back(b);
break;
}
}
}
return res;
}
};This worked but did too much work upfront.
Better Approach: Direct Enumeration
Instead of computing sums, I enumerated powers directly. This cut computation dramatically.
class Solution {
public:
vector<int> powerfulIntegers(int x, int y, int bound) {
unordered_set<int> s;
for (int i = 1; i < bound; i *= x) {
for (int j = 1; i + j <= bound; j *= y) {
s.insert(i + j);
// if y is 1, we only need one iteration before moving to next x
if (y == 1) break;
}
// if x is 1, we only need one full y iteration then exit
if (x == 1) break;
}
return vector<int>(s.begin(), s.end());
}
};Key Insight
When enumerating, choose smaller search spaces. The unordered_set gave me O(1) insertions, avoiding vector resizing costs.
#bruteforce #hashset