forked from halfrost/LeetCode-Go
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
655 additions
and
0 deletions.
There are no files selected for viewing
34 changes: 34 additions & 0 deletions
34
...imum-Moves-to-Make-Array-Complementary/1674. Minimum Moves to Make Array Complementary.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package leetcode | ||
|
||
func minMoves(nums []int, limit int) int { | ||
diff := make([]int, limit*2+2) // nums[i] <= limit, b+limit+1 is maximum limit+limit+1 | ||
for j := 0; j < len(nums)/2; j++ { | ||
a, b := min(nums[j], nums[len(nums)-j-1]), max(nums[j], nums[len(nums)-j-1]) | ||
// using prefix sum: most interesting point, and is the key to reduce complexity | ||
diff[2] += 2 | ||
diff[a+1]-- | ||
diff[a+b]-- | ||
diff[a+b+1]++ | ||
diff[b+limit+1]++ | ||
} | ||
cur, res := 0, len(nums) | ||
for i := 2; i <= 2*limit; i++ { | ||
cur += diff[i] | ||
res = min(res, cur) | ||
} | ||
return res | ||
} | ||
|
||
func min(a, b int) int { | ||
if a < b { | ||
return a | ||
} | ||
return b | ||
} | ||
|
||
func max(a, b int) int { | ||
if a > b { | ||
return a | ||
} | ||
return b | ||
} |
53 changes: 53 additions & 0 deletions
53
...Moves-to-Make-Array-Complementary/1674. Minimum Moves to Make Array Complementary_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package leetcode | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
) | ||
|
||
type question1674 struct { | ||
para1674 | ||
ans1674 | ||
} | ||
|
||
// para 是参数 | ||
// one 代表第一个参数 | ||
type para1674 struct { | ||
nums []int | ||
limit int | ||
} | ||
|
||
// ans 是答案 | ||
// one 代表第一个答案 | ||
type ans1674 struct { | ||
one int | ||
} | ||
|
||
func Test_Problem1674(t *testing.T) { | ||
|
||
qs := []question1674{ | ||
|
||
{ | ||
para1674{[]int{1, 2, 4, 3}, 4}, | ||
ans1674{1}, | ||
}, | ||
|
||
{ | ||
para1674{[]int{1, 2, 2, 1}, 2}, | ||
ans1674{2}, | ||
}, | ||
|
||
{ | ||
para1674{[]int{1, 2, 1, 2}, 2}, | ||
ans1674{0}, | ||
}, | ||
} | ||
|
||
fmt.Printf("------------------------Leetcode Problem 1674------------------------\n") | ||
|
||
for _, q := range qs { | ||
_, p := q.ans1674, q.para1674 | ||
fmt.Printf("【input】:%v 【output】:%v\n", p, minMoves(p.nums, p.limit)) | ||
} | ||
fmt.Printf("\n\n\n") | ||
} |
97 changes: 97 additions & 0 deletions
97
leetcode/1674.Minimum-Moves-to-Make-Array-Complementary/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
# [1674. Minimum Moves to Make Array Complementary](https://leetcode.com/problems/minimum-moves-to-make-array-complementary/) | ||
|
||
## 题目 | ||
|
||
You are given an integer array `nums` of **even** length `n` and an integer `limit`. In one move, you can replace any integer from `nums` with another integer between `1` and `limit`, inclusive. | ||
|
||
The array `nums` is **complementary** if for all indices `i` (**0-indexed**), `nums[i] + nums[n - 1 - i]` equals the same number. For example, the array `[1,2,3,4]` is complementary because for all indices `i`, `nums[i] + nums[n - 1 - i] = 5`. | ||
|
||
Return the ***minimum** number of moves required to make* `nums` ***complementary***. | ||
|
||
**Example 1:** | ||
|
||
``` | ||
Input: nums = [1,2,4,3], limit = 4 | ||
Output: 1 | ||
Explanation: In 1 move, you can change nums to [1,2,2,3] (underlined elements are changed). | ||
nums[0] + nums[3] = 1 + 3 = 4. | ||
nums[1] + nums[2] = 2 + 2 = 4. | ||
nums[2] + nums[1] = 2 + 2 = 4. | ||
nums[3] + nums[0] = 3 + 1 = 4. | ||
Therefore, nums[i] + nums[n-1-i] = 4 for every i, so nums is complementary. | ||
``` | ||
|
||
**Example 2:** | ||
|
||
``` | ||
Input: nums = [1,2,2,1], limit = 2 | ||
Output: 2 | ||
Explanation: In 2 moves, you can change nums to [2,2,2,2]. You cannot change any number to 3 since 3 > limit. | ||
``` | ||
|
||
**Example 3:** | ||
|
||
``` | ||
Input: nums = [1,2,1,2], limit = 2 | ||
Output: 0 | ||
Explanation: nums is already complementary. | ||
``` | ||
|
||
**Constraints:** | ||
|
||
- `n == nums.length` | ||
- `2 <= n <= 105` | ||
- `1 <= nums[i] <= limit <= 105` | ||
- `n` is even. | ||
|
||
## 题目大意 | ||
|
||
给你一个长度为 偶数 n 的整数数组 nums 和一个整数 limit 。每一次操作,你可以将 nums 中的任何整数替换为 1 到 limit 之间的另一个整数。 | ||
|
||
如果对于所有下标 i(下标从 0 开始),nums[i] + nums[n - 1 - i] 都等于同一个数,则数组 nums 是 互补的 。例如,数组 [1,2,3,4] 是互补的,因为对于所有下标 i ,nums[i] + nums[n - 1 - i] = 5 。 | ||
|
||
返回使数组 互补 的 最少 操作次数。 | ||
|
||
## 解题思路 | ||
|
||
- 这一题考察的是差分数组。通过分析题意,可以得出,针对每一个 `sum` 的取值范围是 `[2, 2* limt]`,定义 `a = min(nums[i], nums[n - i - 1])`,`b = max(nums[i], nums[n - i - 1])`,在这个区间内,又可以细分成 5 个区间,`[2, a + 1)`,`[a + 1, a + b)`,`[a + b + 1, a + b + 1)`,`[a + b + 1, b + limit + 1)`,`[b + limit + 1, 2 * limit)`,在这 5 个区间内使得数组互补的最小操作次数分别是 `2(减少 a, 减少 b)`,`1(减少 b)`,`0(不用操作)`,`1(增大 a)`,`+2(增大 a, 增大 b)`,换个表达方式,按照扫描线从左往右扫描,在这 5 个区间内使得数组互补的最小操作次数叠加变化分别是 `+2(减少 a, 减少 b)`,`-1(减少 a)`,`-1(不用操作)`,`+1(增大 a)`,`+1(增大 a, 增大 b)`,利用这前后两个区间的关系,就可以构造一个差分数组。差分数组反应的是前后两者的关系。如果想求得 0 ~ n 的总关系,只需要求一次前缀和即可。 | ||
- 这道题要求输出最少的操作次数,所以利用差分数组 + 前缀和,累加前缀和的同时维护最小值。从左往右扫描完一遍以后,输出最小值即可。 | ||
|
||
## 代码 | ||
|
||
```go | ||
package leetcode | ||
|
||
func minMoves(nums []int, limit int) int { | ||
diff := make([]int, limit*2+2) // nums[i] <= limit, b+limit+1 is maximum limit+limit+1 | ||
for j := 0; j < len(nums)/2; j++ { | ||
a, b := min(nums[j], nums[len(nums)-j-1]), max(nums[j], nums[len(nums)-j-1]) | ||
// using prefix sum: most interesting point, and is the key to reduce complexity | ||
diff[2] += 2 | ||
diff[a+1]-- | ||
diff[a+b]-- | ||
diff[a+b+1]++ | ||
diff[b+limit+1]++ | ||
} | ||
cur, res := 0, len(nums) | ||
for i := 2; i <= 2*limit; i++ { | ||
cur += diff[i] | ||
res = min(res, cur) | ||
} | ||
return res | ||
} | ||
|
||
func min(a, b int) int { | ||
if a < b { | ||
return a | ||
} | ||
return b | ||
} | ||
|
||
func max(a, b int) int { | ||
if a > b { | ||
return a | ||
} | ||
return b | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package leetcode | ||
|
||
// 解法一 优化空间版 DP | ||
func stoneGameVII(stones []int) int { | ||
n := len(stones) | ||
sum := make([]int, n) | ||
dp := make([]int, n) | ||
for i, d := range stones { | ||
sum[i] = d | ||
} | ||
for i := 1; i < n; i++ { | ||
for j := 0; j+i < n; j++ { | ||
if (n-i)%2 == 1 { | ||
d0 := dp[j] + sum[j] | ||
d1 := dp[j+1] + sum[j+1] | ||
if d0 > d1 { | ||
dp[j] = d0 | ||
} else { | ||
dp[j] = d1 | ||
} | ||
} else { | ||
d0 := dp[j] - sum[j] | ||
d1 := dp[j+1] - sum[j+1] | ||
if d0 < d1 { | ||
dp[j] = d0 | ||
} else { | ||
dp[j] = d1 | ||
} | ||
} | ||
sum[j] = sum[j] + stones[i+j] | ||
} | ||
} | ||
return dp[0] | ||
} | ||
|
||
// 解法二 常规 DP | ||
func stoneGameVII1(stones []int) int { | ||
prefixSum := make([]int, len(stones)) | ||
for i := 0; i < len(stones); i++ { | ||
if i == 0 { | ||
prefixSum[i] = stones[i] | ||
} else { | ||
prefixSum[i] = prefixSum[i-1] + stones[i] | ||
} | ||
} | ||
dp := make([][]int, len(stones)) | ||
for i := range dp { | ||
dp[i] = make([]int, len(stones)) | ||
dp[i][i] = 0 | ||
} | ||
n := len(stones) | ||
for l := 2; l <= n; l++ { | ||
for i := 0; i+l <= n; i++ { | ||
dp[i][i+l-1] = max(prefixSum[i+l-1]-prefixSum[i+1]+stones[i+1]-dp[i+1][i+l-1], prefixSum[i+l-2]-prefixSum[i]+stones[i]-dp[i][i+l-2]) | ||
} | ||
} | ||
return dp[0][n-1] | ||
} | ||
|
||
func max(a, b int) int { | ||
if a > b { | ||
return a | ||
} | ||
return b | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package leetcode | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
) | ||
|
||
type question1690 struct { | ||
para1690 | ||
ans1690 | ||
} | ||
|
||
// para 是参数 | ||
// one 代表第一个参数 | ||
type para1690 struct { | ||
stones []int | ||
} | ||
|
||
// ans 是答案 | ||
// one 代表第一个答案 | ||
type ans1690 struct { | ||
one int | ||
} | ||
|
||
func Test_Problem1690(t *testing.T) { | ||
|
||
qs := []question1690{ | ||
|
||
{ | ||
para1690{[]int{5, 3, 1, 4, 2}}, | ||
ans1690{6}, | ||
}, | ||
|
||
{ | ||
para1690{[]int{7, 90, 5, 1, 100, 10, 10, 2}}, | ||
ans1690{122}, | ||
}, | ||
} | ||
|
||
fmt.Printf("------------------------Leetcode Problem 1690------------------------\n") | ||
|
||
for _, q := range qs { | ||
_, p := q.ans1690, q.para1690 | ||
fmt.Printf("【input】:%v 【output】:%v\n", p, stoneGameVII(p.stones)) | ||
} | ||
fmt.Printf("\n\n\n") | ||
} |
Oops, something went wrong.