Skip to content

feat: add solutions to lc problem: No.2139 #1725

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 123 additions & 5 deletions solution/2100-2199/2139.Minimum Moves to Reach Target Score/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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))$。

我们也可以将上述过程改为迭代的方式,这样可以避免递归的空间开销。

<!-- tabs:start -->

### **Python3**
Expand All @@ -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**

<!-- 这里可写当前语言的特殊实现逻辑 -->
Expand All @@ -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
Expand All @@ -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;
}
```

### **...**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.

<!-- tabs:start -->

### **Python3**
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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;
}
```

### **...**
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
};
Original file line number Diff line number Diff line change
@@ -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
}
Loading