[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. 1 <= X <= 10^9
  2. 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

posted @ 2020-08-23 04:57  Review->Improve  阅读(239)  评论(0编辑  收藏  举报