The Broken Calculator problem on LeetCode asks you to compute the minimum number of operations needed to transform a starting value startValue into a target value target using only two operations:
x = x * 2).x = x - 1).
You can use these operations in any order and as many times as needed. Your task is to return the minimum number of operations needed to transform startValue into target.
Constraints:
startValue, target ≤ 109
At first glance, it’s tempting to simulate every possible sequence of operations from startValue to target. However, this brute-force approach is inefficient, especially for large numbers, because the number of possible sequences grows exponentially.
Instead, we can reverse our thinking: rather than moving from startValue up to target, what if we start from target and work backwards to startValue? This is possible because:
This reversal allows us to minimize the number of operations by halving the target whenever possible, which is generally more efficient than subtracting 1 repeatedly.
Let's break down the optimized approach step by step:
target and try to reduce it to startValue using the reverse operations:
target is even, divide it by 2 (since this is the reverse of multiplying by 2).target is odd, add 1 (since this is the reverse of subtracting 1).target becomes less than or equal to startValue.
target is now less than startValue, we can only use the subtract 1 operation (forward) to reach target from startValue. This requires startValue - target additional steps.
This method is efficient because dividing by 2 reduces the number much faster than subtracting 1 repeatedly, and we only subtract when necessary (i.e., when the number is odd).
Example: startValue = 5, target = 8
Brute-force approach:
O(\log{target}) because we halve the target at each step (when possible), leading to logarithmic steps.O(1) since we only use a few variables for counters and current values.The Broken Calculator problem demonstrates the power of working backwards from the target to the start, transforming a potentially exponential brute-force search into an efficient logarithmic algorithm. By always dividing by 2 when possible and only subtracting when necessary, we minimize the number of steps. This approach is both elegant and practical, making it suitable for very large input values.
class Solution:
def brokenCalc(self, startValue: int, target: int) -> int:
operations = 0
while target > startValue:
if target % 2 == 0:
target //= 2
else:
target += 1
operations += 1
return operations + (startValue - target)
class Solution {
public:
int brokenCalc(int startValue, int target) {
int operations = 0;
while (target > startValue) {
if (target % 2 == 0) {
target /= 2;
} else {
target += 1;
}
operations++;
}
return operations + (startValue - target);
}
};
class Solution {
public int brokenCalc(int startValue, int target) {
int operations = 0;
while (target > startValue) {
if (target % 2 == 0) {
target /= 2;
} else {
target += 1;
}
operations++;
}
return operations + (startValue - target);
}
}
var brokenCalc = function(startValue, target) {
let operations = 0;
while (target > startValue) {
if (target % 2 === 0) {
target = target / 2;
} else {
target = target + 1;
}
operations++;
}
return operations + (startValue - target);
};