You are playing a game with integers. You start with the integer 1
and you want to reach the integer target
.
In one move, you can either:
x = x + 1
).x = 2 * x
).You can use the increment operation any number of times, however, you can only use the double operation at most maxDoubles
times.
Given the two integers target
and maxDoubles
, return the minimum number of moves needed to reach target
starting with 1
.
Example 1:
Input: target = 5, maxDoubles = 0
Output: 4
Explanation: Keep incrementing by 1 until you reach target.
Example 2:
Input: target = 19, maxDoubles = 2
Output: 7
Explanation: Initially, x = 1
Increment 3 times so x = 4
Double once so x = 8
Increment once so x = 9
Double again so x = 18
Increment once so x = 19
Example 3:
Input: target = 10, maxDoubles = 4
Output: 4
Explanation: Initially, x = 1
Increment once so x = 2
Double once so x = 4
Increment once so x = 5
Double again so x = 10
The most straightforward approach is to simply increment from 1 until we reach the target. If maxDoubles
is greater than 0, we can explore doubling at each step and then recursively check the number of operations required to reach target.
This brute-force approach will explore all possible paths of incrementing and doubling (up to maxDoubles
doublings) until we find the minimum number of operations.
However, it can be very inefficient, especially for large targets and maxDoubles
, leading to a time limit exceeded error.
Instead of working forwards from 1 to the target, let's work backward from the target to 1.
If the target is even, we can divide it by 2 if we have any doubles available. If we don't have any doubles available or if the target is odd, we decrement by 1.
We repeat this process until the target becomes 1. This approach ensures that we use doubling operations as much as possible when the target is even, thereby minimizing the overall number of operations.
Here's a breakdown:
moves
to 0.target
is greater than 1:
maxDoubles
is greater than 0 and target
is even:
target
by 2.maxDoubles
.moves
.maxDoubles
is 0, increment target until it becomes odd to use decrement efficiently.target
by 1.moves
.moves
.target
is 1, the number of moves is 0.maxDoubles
is 0, the number of moves is target - 1
.class Solution {
public int minMoves(int target, int maxDoubles) {
int moves = 0;
while (target > 1) {
if (maxDoubles > 0 && target % 2 == 0) {
target /= 2;
maxDoubles--;
moves++;
} else {
if (maxDoubles == 0) {
return moves + target -1;
}
target--;
moves++;
}
}
return moves;
}
}
maxDoubles
is 0 or very small compared to the number of decrements required), and O(log target) in the best case (when we can divide target multiple times and maxDoubles is large enough). In any case, it's significantly better than exponential time complexity of brute force.