[LeetCode 991] Broken Calculator
On a broken calculator that has a number showing on its display, we can perform two operations:
- Double: Multiply the number on the display by 2, or;
- Decrement: Subtract 1 from the number on the display.
Initially, the calculator is displaying the number X
.
Return the minimum number of operations needed to display the number Y
.
Example 1:
Input: X = 2, Y = 3
Output: 2
Explanation: Use double operation and then decrement operation {2 -> 4 -> 3}.
Example 2:
Input: X = 5, Y = 8
Output: 2
Explanation: Use decrement and then double {5 -> 4 -> 8}.
Example 3:
Input: X = 3, Y = 10
Output: 3
Explanation: Use double, decrement and double {3 -> 6 -> 5 -> 10}.
Example 4:
Input: X = 1024, Y = 1
Output: 1023
Explanation: Use decrement operations 1023 times.
Note:
1 <= X <= 10^9
1 <= Y <= 10^9
This problem shares the exact same principle with the following related problem: Going forward from X to Y is incorrect. We need to go backward from Y to X.
Counter example: X = 3, Y = 10.
Incorrect forward sequence of cost 4: 3 -> 6 -> 12 -> 11 -> 10;
Correct forward sequence of cost 3: 3 -> 6 -> 5 -> 10;
Incorrect Solution
class Solution { public int brokenCalc(int X, int Y) { if(X >= Y) { return X - Y; } int op = 0; while(X < Y) { X *= 2; op++; } while(X != Y) { X--; op++; } return op; } }
Correct Solution
class Solution { public int brokenCalc(int X, int Y) { //if X >= Y, we can only use decrement if(X >= Y) { return X - Y; } int op = 0; while(Y > X) { //if Y is odd, it means that we would go from a smaller value (Y + 1) / 2 to Y + 1, which is even, //then perform a decrement to reach Y. if(Y % 2 != 0) { Y++; op++; } //Y is even, it means that we would go from Y / 2 by double operation Y /= 2; op++; } //X - Y represents the decrement operations we need to perform at the beginning return op + (X - Y); } }
TLE BFS solution
The runtime of the above solution is O(logY). However since we are looking for the minimum number of operations, each operation can be considered as a graph node hop, we can use BFS to solve this problem. For Y that is O(10^6), it can compute the correct answer within the time limit. For bigger Y, this solution falls off since it takes O(Y) time and space.
class Solution { public int brokenCalc(int X, int Y) { if(X >= Y) { return X - Y; } Deque<Integer> q = new ArrayDeque<>(); Set<Integer> visited = new HashSet<>(); q.addLast(X); visited.add(X); int op = 0; boolean reach = false; while(true) { int sz = q.size(); for(int i = 0; i < sz; i++) { int v = q.pollFirst(); if(v == Y) { reach = true; break; } if(v < Y) { long u = (long)v * 2; if(u < Integer.MAX_VALUE && !visited.contains((int)u)) { q.addLast((int)u); visited.add((int)u); } } if(v - 1 > 0 && !visited.contains(v - 1)) { q.addLast(v - 1); visited.add(v - 1); } } if(reach) { break; } op++; } return op; } }
Related Problems
[LeetCode 1558] Minimum Numbers of Function Calls to Make Target Array