{x}
blog image

Broken Calculator

There is a broken calculator that has the integer startValue on its display initially. In one operation, you can:

  • multiply the number on display by 2, or
  • subtract 1 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

Solution Explanation

The problem asks for the minimum number of operations to transform startValue into target using only multiplication by 2 or subtraction by 1. A greedy approach works best here. The core idea is to work backward from the target to startValue, prioritizing division by 2 (when possible) because it's more efficient than multiple subtractions.

Algorithm:

  1. Work Backwards: Instead of starting from startValue, we begin from target and iteratively reduce it towards startValue.

  2. Prioritize Division: If target is even, we can divide it by 2, representing a single multiplication operation in the reverse direction (going from startValue to target).

  3. Handle Odd Numbers: If target is odd, we can't divide it by 2. Instead, we increment it by 1, simulating a subtraction operation in the reverse direction. This is because subtracting 1 from an odd number makes it even, and the next step can perform a more efficient division.

  4. Final Subtraction: Once target becomes less than or equal to startValue, any remaining difference is handled by simple subtractions. The number of subtractions is simply startValue - target.

Time Complexity Analysis:

The while loop continues as long as target is greater than startValue. In each iteration, target is either halved (in the best case) or incremented by one (in the worst case). The worst-case scenario is when target is much larger than startValue and involves many increment operations before a division becomes possible. However, the number of operations is still logarithmic with respect to the difference between target and startValue.

  • Best Case: O(log₂(target - startValue)). This happens when target is a power of 2.
  • Worst Case: O(target - startValue). This happens when target is odd and much larger than startValue. However, this is still linear with respect to the difference, not the values themselves.

Therefore, the overall time complexity is considered to be O(log₂(target)) in a practical sense, which is quite efficient.

Space Complexity Analysis:

The algorithm uses a constant amount of extra space to store variables like ans and target. Thus, the space complexity is O(1).

Code Explanation (Python3 Example)

class Solution:
    def brokenCalc(self, startValue: int, target: int) -> int:
        ans = 0
        while startValue < target:
            if target & 1:  # Check if target is odd using bitwise AND
                target += 1
            else:
                target >>= 1  # Divide target by 2 using right bit shift
            ans += 1
        ans += startValue - target  # Add final subtractions
        return ans

This code directly implements the algorithm described above. The bitwise operations (& 1 and >>= 1) are efficient ways to check for odd numbers and perform division by 2, respectively. The rest of the code follows the steps outlined in the algorithm. The other language examples (Java, C++, Go) are analogous in their implementation and complexity.