There is a broken calculator that has the integer startValue
on its display initially. In one operation, you can:
2
, or1
from the number on display.Given two integers startValue
and target
, return the minimum number of operations needed to display target
on the calculator.
Example 1:
Input: startValue = 2, target = 3 Output: 2 Explanation: Use double operation and then decrement operation {2 -> 4 -> 3}.
Example 2:
Input: startValue = 5, target = 8 Output: 2 Explanation: Use decrement and then double {5 -> 4 -> 8}.
Example 3:
Input: startValue = 3, target = 10 Output: 3 Explanation: Use double, decrement and double {3 -> 6 -> 5 -> 10}.
Constraints:
1 <= startValue, target <= 109
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The goal is to transform a starting number into a target number using only multiplication by two and subtraction by one. A brute force approach would explore every possible combination of these operations until we find the target.
Here's how the algorithm would work step-by-step:
def broken_calculator_brute_force(start_value, target_value):
queue = [(start_value, 0)]
minimum_operations = float('inf')
while queue:
current_value, current_operations = queue.pop(0)
# If target is found, check if it's the minimum operations
if current_value == target_value:
minimum_operations = min(minimum_operations, current_operations)
# Only explore further if the current path isn't longer than the best so far
if current_operations >= minimum_operations:
continue
# Optimization: Don't explore paths that go too far beyond the target
if current_value > (target_value + 1000):
continue
# Check for multiplication possibility
new_value_multiply = current_value * 2
queue.append((new_value_multiply, current_operations + 1))
# Check for subtraction possibility
new_value_subtract = current_value - 1
queue.append((new_value_subtract, current_operations + 1))
return minimum_operations
The key to solving this problem efficiently is to work backward from the target value. Instead of multiplying and subtracting from the start value, we divide and add to reach the start value, because there are only two allowed operations.
Here's how the algorithm would work step-by-step:
def broken_calculator(start_value, target_value):
number_of_operations = 0
while target_value > start_value:
# If target is even, divide to reduce faster
if target_value % 2 == 0:
target_value //= 2
number_of_operations += 1
# If target is odd, add 1 to make it even
else:
target_value += 1
number_of_operations += 1
# If target is smaller, add the difference
number_of_operations += start_value - target_value
return number_of_operations
Case | How to Handle |
---|---|
startValue equals target | Return 0 immediately as no operations are needed. |
startValue is greater than target | Only subtraction is possible, so return startValue - target. |
target is 1 | Repeated subtraction is required, so return startValue - 1. |
startValue and target are very large numbers potentially causing integer overflow during multiplication | Avoid direct multiplication when startValue is small and target is large, instead work backwards from target towards startValue using division and addition. |
target is even, and startValue needs to be multiplied before a subtraction | Account for all possibilities of *2 and -1 while working backward from target, if possible. |
startValue is 1 | The optimal solution involves multiplications followed by subtractions from the multiplied values. |
startValue and target are close but require a mix of multiplication and subtraction | Backtracking or BFS ensures finding the optimal path, correctly mixing *2 and -1. |
Maximum recursion depth could be exceeded | Employ iterative solution with a queue, such as BFS, to avoid stack overflow. |