diff --git a/solution/2100-2199/2139.Minimum Moves to Reach Target Score/README.md b/solution/2100-2199/2139.Minimum Moves to Reach Target Score/README.md index aa1fed4c1df6c..df9887b70d101 100644 --- a/solution/2100-2199/2139.Minimum Moves to Reach Target Score/README.md +++ b/solution/2100-2199/2139.Minimum Moves to Reach Target Score/README.md @@ -65,6 +65,22 @@ +**方法一:倒推 + 贪心** + +我们不妨从最终的状态开始倒推,假设最终的状态为 $target$,那么我们可以得到 $target$ 的前一个状态为 $target - 1$ 或者 $target / 2$,这取决于 $target$ 的奇偶性以及 $maxDoubles$ 的值。 + +如果 $target=1$,那么不需要任何操作,直接返回 $0$ 即可。 + +如果 $maxDoubles=0$,那么我们只能使用递增操作,因此我们需要 $target-1$ 次操作。 + +如果 $target$ 是偶数且 $maxDoubles>0$,那么我们可以使用加倍操作,因此我们需要 $1$ 次操作,然后递归求解 $target/2$ 和 $maxDoubles-1$。 + +如果 $target$ 是奇数,那么我们只能使用递增操作,因此我们需要 $1$ 次操作,然后递归求解 $target-1$ 和 $maxDoubles$。 + +时间复杂度 $O(\min(\log target, maxDoubles))$,空间复杂度 $O(\min(\log target, maxDoubles))$。 + +我们也可以将上述过程改为迭代的方式,这样可以避免递归的空间开销。 + ### **Python3** @@ -83,6 +99,21 @@ class Solution: return 1 + self.minMoves(target - 1, maxDoubles) ``` +```python +class Solution: + def minMoves(self, target: int, maxDoubles: int) -> int: + ans = 0 + while maxDoubles and target > 1: + ans += 1 + if target % 2 == 1: + target -= 1 + else: + maxDoubles -= 1 + target >>= 1 + ans += target - 1 + return ans +``` + ### **Java** @@ -104,20 +135,65 @@ class Solution { } ``` +```java +class Solution { + public int minMoves(int target, int maxDoubles) { + int ans = 0; + while (maxDoubles > 0 && target > 1) { + ++ans; + if (target % 2 == 1) { + --target; + } else { + --maxDoubles; + target >>= 1; + } + } + ans += target - 1; + return ans; + } +} +``` + ### **C++** ```cpp class Solution { public: int minMoves(int target, int maxDoubles) { - if (target == 1) return 0; - if (maxDoubles == 0) return target - 1; - if (target % 2 == 0 && maxDoubles) return 1 + minMoves(target >> 1, maxDoubles - 1); + if (target == 1) { + return 0; + } + if (maxDoubles == 0) { + return target - 1; + } + if (target % 2 == 0 && maxDoubles > 0) { + return 1 + minMoves(target >> 1, maxDoubles - 1); + } return 1 + minMoves(target - 1, maxDoubles); } }; ``` +```cpp +class Solution { +public: + int minMoves(int target, int maxDoubles) { + int ans = 0; + while (maxDoubles > 0 && target > 1) { + ++ans; + if (target % 2 == 1) { + --target; + } else { + --maxDoubles; + target >>= 1; + } + } + ans += target - 1; + return ans; + } +}; +``` + ### **Go** ```go @@ -135,12 +211,54 @@ func minMoves(target int, maxDoubles int) int { } ``` -### **TypeScript** +```go +func minMoves(target int, maxDoubles int) (ans int) { + for maxDoubles > 0 && target > 1 { + ans++ + if target&1 == 1 { + target-- + } else { + maxDoubles-- + target >>= 1 + } + } + ans += target - 1 + return +} +``` - +### **TypeScript** ```ts +function minMoves(target: number, maxDoubles: number): number { + if (target === 1) { + return 0; + } + if (maxDoubles === 0) { + return target - 1; + } + if (target % 2 === 0 && maxDoubles) { + return 1 + minMoves(target >> 1, maxDoubles - 1); + } + return 1 + minMoves(target - 1, maxDoubles); +} +``` +```ts +function minMoves(target: number, maxDoubles: number): number { + let ans = 0; + while (maxDoubles && target > 1) { + ++ans; + if (target & 1) { + --target; + } else { + --maxDoubles; + target >>= 1; + } + } + ans += target - 1; + return ans; +} ``` ### **...** diff --git a/solution/2100-2199/2139.Minimum Moves to Reach Target Score/README_EN.md b/solution/2100-2199/2139.Minimum Moves to Reach Target Score/README_EN.md index 62fc9a3d79570..e1e1c0ae6b8bb 100644 --- a/solution/2100-2199/2139.Minimum Moves to Reach Target Score/README_EN.md +++ b/solution/2100-2199/2139.Minimum Moves to Reach Target Score/README_EN.md @@ -61,6 +61,22 @@ Double again so x = 10 ## Solutions +**Solution 1: Backtracking + Greedy** + +Let's start by backtracking from the final state. Assuming the final state is $target$, we can get the previous state of $target$ as $target - 1$ or $target / 2$, depending on the parity of $target$ and the value of $maxDoubles$. + +If $target=1$, no operation is needed, and we can return $0$ directly. + +If $maxDoubles=0$, we can only use the increment operation, so we need $target-1$ operations. + +If $target$ is even and $maxDoubles>0$, we can use the doubling operation, so we need $1$ operation, and then recursively solve $target/2$ and $maxDoubles-1$. + +If $target$ is odd, we can only use the increment operation, so we need $1$ operation, and then recursively solve $target-1$ and $maxDoubles$. + +The time complexity is $O(\min(\log target, maxDoubles))$, and the space complexity is $O(\min(\log target, maxDoubles))$. + +We can also change the above process to an iterative way to avoid the space overhead of recursion. + ### **Python3** @@ -77,6 +93,21 @@ class Solution: return 1 + self.minMoves(target - 1, maxDoubles) ``` +```python +class Solution: + def minMoves(self, target: int, maxDoubles: int) -> int: + ans = 0 + while maxDoubles and target > 1: + ans += 1 + if target % 2 == 1: + target -= 1 + else: + maxDoubles -= 1 + target >>= 1 + ans += target - 1 + return ans +``` + ### **Java** ```java @@ -96,20 +127,65 @@ class Solution { } ``` +```java +class Solution { + public int minMoves(int target, int maxDoubles) { + int ans = 0; + while (maxDoubles > 0 && target > 1) { + ++ans; + if (target % 2 == 1) { + --target; + } else { + --maxDoubles; + target >>= 1; + } + } + ans += target - 1; + return ans; + } +} +``` + ### **C++** ```cpp class Solution { public: int minMoves(int target, int maxDoubles) { - if (target == 1) return 0; - if (maxDoubles == 0) return target - 1; - if (target % 2 == 0 && maxDoubles) return 1 + minMoves(target >> 1, maxDoubles - 1); + if (target == 1) { + return 0; + } + if (maxDoubles == 0) { + return target - 1; + } + if (target % 2 == 0 && maxDoubles > 0) { + return 1 + minMoves(target >> 1, maxDoubles - 1); + } return 1 + minMoves(target - 1, maxDoubles); } }; ``` +```cpp +class Solution { +public: + int minMoves(int target, int maxDoubles) { + int ans = 0; + while (maxDoubles > 0 && target > 1) { + ++ans; + if (target % 2 == 1) { + --target; + } else { + --maxDoubles; + target >>= 1; + } + } + ans += target - 1; + return ans; + } +}; +``` + ### **Go** ```go @@ -127,10 +203,54 @@ func minMoves(target int, maxDoubles int) int { } ``` +```go +func minMoves(target int, maxDoubles int) (ans int) { + for maxDoubles > 0 && target > 1 { + ans++ + if target&1 == 1 { + target-- + } else { + maxDoubles-- + target >>= 1 + } + } + ans += target - 1 + return +} +``` + ### **TypeScript** ```ts +function minMoves(target: number, maxDoubles: number): number { + if (target === 1) { + return 0; + } + if (maxDoubles === 0) { + return target - 1; + } + if (target % 2 === 0 && maxDoubles) { + return 1 + minMoves(target >> 1, maxDoubles - 1); + } + return 1 + minMoves(target - 1, maxDoubles); +} +``` +```ts +function minMoves(target: number, maxDoubles: number): number { + let ans = 0; + while (maxDoubles && target > 1) { + ++ans; + if (target & 1) { + --target; + } else { + --maxDoubles; + target >>= 1; + } + } + ans += target - 1; + return ans; +} ``` ### **...** diff --git a/solution/2100-2199/2139.Minimum Moves to Reach Target Score/Solution.cpp b/solution/2100-2199/2139.Minimum Moves to Reach Target Score/Solution.cpp index 2a6be741e31a7..6ecfd244689cf 100644 --- a/solution/2100-2199/2139.Minimum Moves to Reach Target Score/Solution.cpp +++ b/solution/2100-2199/2139.Minimum Moves to Reach Target Score/Solution.cpp @@ -1,9 +1,17 @@ class Solution { public: int minMoves(int target, int maxDoubles) { - if (target == 1) return 0; - if (maxDoubles == 0) return target - 1; - if (target % 2 == 0 && maxDoubles) return 1 + minMoves(target >> 1, maxDoubles - 1); - return 1 + minMoves(target - 1, maxDoubles); + int ans = 0; + while (maxDoubles > 0 && target > 1) { + ++ans; + if (target % 2 == 1) { + --target; + } else { + --maxDoubles; + target >>= 1; + } + } + ans += target - 1; + return ans; } }; \ No newline at end of file diff --git a/solution/2100-2199/2139.Minimum Moves to Reach Target Score/Solution.go b/solution/2100-2199/2139.Minimum Moves to Reach Target Score/Solution.go index 200d0ee48b026..0a7b08de6a694 100644 --- a/solution/2100-2199/2139.Minimum Moves to Reach Target Score/Solution.go +++ b/solution/2100-2199/2139.Minimum Moves to Reach Target Score/Solution.go @@ -1,12 +1,13 @@ -func minMoves(target int, maxDoubles int) int { - if target == 1 { - return 0 +func minMoves(target int, maxDoubles int) (ans int) { + for maxDoubles > 0 && target > 1 { + ans++ + if target&1 == 1 { + target-- + } else { + maxDoubles-- + target >>= 1 + } } - if maxDoubles == 0 { - return target - 1 - } - if target%2 == 0 && maxDoubles > 0 { - return 1 + minMoves(target>>1, maxDoubles-1) - } - return 1 + minMoves(target-1, maxDoubles) + ans += target - 1 + return } \ No newline at end of file diff --git a/solution/2100-2199/2139.Minimum Moves to Reach Target Score/Solution.java b/solution/2100-2199/2139.Minimum Moves to Reach Target Score/Solution.java index 8764ce3688d3f..0d40a3e55eda5 100644 --- a/solution/2100-2199/2139.Minimum Moves to Reach Target Score/Solution.java +++ b/solution/2100-2199/2139.Minimum Moves to Reach Target Score/Solution.java @@ -1,14 +1,16 @@ class Solution { public int minMoves(int target, int maxDoubles) { - if (target == 1) { - return 0; + int ans = 0; + while (maxDoubles > 0 && target > 1) { + ++ans; + if (target % 2 == 1) { + --target; + } else { + --maxDoubles; + target >>= 1; + } } - if (maxDoubles == 0) { - return target - 1; - } - if (target % 2 == 0 && maxDoubles > 0) { - return 1 + minMoves(target >> 1, maxDoubles - 1); - } - return 1 + minMoves(target - 1, maxDoubles); + ans += target - 1; + return ans; } } \ No newline at end of file diff --git a/solution/2100-2199/2139.Minimum Moves to Reach Target Score/Solution.py b/solution/2100-2199/2139.Minimum Moves to Reach Target Score/Solution.py index 2e76193c48c9a..92c04a2b7973a 100644 --- a/solution/2100-2199/2139.Minimum Moves to Reach Target Score/Solution.py +++ b/solution/2100-2199/2139.Minimum Moves to Reach Target Score/Solution.py @@ -1,9 +1,12 @@ class Solution: def minMoves(self, target: int, maxDoubles: int) -> int: - if target == 1: - return 0 - if maxDoubles == 0: - return target - 1 - if target % 2 == 0 and maxDoubles: - return 1 + self.minMoves(target >> 1, maxDoubles - 1) - return 1 + self.minMoves(target - 1, maxDoubles) + ans = 0 + while maxDoubles and target > 1: + ans += 1 + if target % 2 == 1: + target -= 1 + else: + maxDoubles -= 1 + target >>= 1 + ans += target - 1 + return ans diff --git a/solution/2100-2199/2139.Minimum Moves to Reach Target Score/Solution.ts b/solution/2100-2199/2139.Minimum Moves to Reach Target Score/Solution.ts new file mode 100644 index 0000000000000..9d5022b8d2063 --- /dev/null +++ b/solution/2100-2199/2139.Minimum Moves to Reach Target Score/Solution.ts @@ -0,0 +1,14 @@ +function minMoves(target: number, maxDoubles: number): number { + let ans = 0; + while (maxDoubles && target > 1) { + ++ans; + if (target & 1) { + --target; + } else { + --maxDoubles; + target >>= 1; + } + } + ans += target - 1; + return ans; +}