Skip to content

Commit e3fd0d2

Browse files
committed
Add solution 1674、1690
1 parent e85f323 commit e3fd0d2

File tree

9 files changed

+655
-0
lines changed

9 files changed

+655
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package leetcode
2+
3+
func minMoves(nums []int, limit int) int {
4+
diff := make([]int, limit*2+2) // nums[i] <= limit, b+limit+1 is maximum limit+limit+1
5+
for j := 0; j < len(nums)/2; j++ {
6+
a, b := min(nums[j], nums[len(nums)-j-1]), max(nums[j], nums[len(nums)-j-1])
7+
// using prefix sum: most interesting point, and is the key to reduce complexity
8+
diff[2] += 2
9+
diff[a+1]--
10+
diff[a+b]--
11+
diff[a+b+1]++
12+
diff[b+limit+1]++
13+
}
14+
cur, res := 0, len(nums)
15+
for i := 2; i <= 2*limit; i++ {
16+
cur += diff[i]
17+
res = min(res, cur)
18+
}
19+
return res
20+
}
21+
22+
func min(a, b int) int {
23+
if a < b {
24+
return a
25+
}
26+
return b
27+
}
28+
29+
func max(a, b int) int {
30+
if a > b {
31+
return a
32+
}
33+
return b
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package leetcode
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
)
7+
8+
type question1674 struct {
9+
para1674
10+
ans1674
11+
}
12+
13+
// para 是参数
14+
// one 代表第一个参数
15+
type para1674 struct {
16+
nums []int
17+
limit int
18+
}
19+
20+
// ans 是答案
21+
// one 代表第一个答案
22+
type ans1674 struct {
23+
one int
24+
}
25+
26+
func Test_Problem1674(t *testing.T) {
27+
28+
qs := []question1674{
29+
30+
{
31+
para1674{[]int{1, 2, 4, 3}, 4},
32+
ans1674{1},
33+
},
34+
35+
{
36+
para1674{[]int{1, 2, 2, 1}, 2},
37+
ans1674{2},
38+
},
39+
40+
{
41+
para1674{[]int{1, 2, 1, 2}, 2},
42+
ans1674{0},
43+
},
44+
}
45+
46+
fmt.Printf("------------------------Leetcode Problem 1674------------------------\n")
47+
48+
for _, q := range qs {
49+
_, p := q.ans1674, q.para1674
50+
fmt.Printf("【input】:%v 【output】:%v\n", p, minMoves(p.nums, p.limit))
51+
}
52+
fmt.Printf("\n\n\n")
53+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# [1674. Minimum Moves to Make Array Complementary](https://leetcode.com/problems/minimum-moves-to-make-array-complementary/)
2+
3+
## 题目
4+
5+
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.
6+
7+
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`.
8+
9+
Return the ***minimum** number of moves required to make* `nums` ***complementary***.
10+
11+
**Example 1:**
12+
13+
```
14+
Input: nums = [1,2,4,3], limit = 4
15+
Output: 1
16+
Explanation: In 1 move, you can change nums to [1,2,2,3] (underlined elements are changed).
17+
nums[0] + nums[3] = 1 + 3 = 4.
18+
nums[1] + nums[2] = 2 + 2 = 4.
19+
nums[2] + nums[1] = 2 + 2 = 4.
20+
nums[3] + nums[0] = 3 + 1 = 4.
21+
Therefore, nums[i] + nums[n-1-i] = 4 for every i, so nums is complementary.
22+
```
23+
24+
**Example 2:**
25+
26+
```
27+
Input: nums = [1,2,2,1], limit = 2
28+
Output: 2
29+
Explanation: In 2 moves, you can change nums to [2,2,2,2]. You cannot change any number to 3 since 3 > limit.
30+
```
31+
32+
**Example 3:**
33+
34+
```
35+
Input: nums = [1,2,1,2], limit = 2
36+
Output: 0
37+
Explanation: nums is already complementary.
38+
```
39+
40+
**Constraints:**
41+
42+
- `n == nums.length`
43+
- `2 <= n <= 105`
44+
- `1 <= nums[i] <= limit <= 105`
45+
- `n` is even.
46+
47+
## 题目大意
48+
49+
给你一个长度为 偶数 n 的整数数组 nums 和一个整数 limit 。每一次操作,你可以将 nums 中的任何整数替换为 1 到 limit 之间的另一个整数。
50+
51+
如果对于所有下标 i(下标从 0 开始),nums[i] + nums[n - 1 - i] 都等于同一个数,则数组 nums 是 互补的 。例如,数组 [1,2,3,4] 是互补的,因为对于所有下标 i ,nums[i] + nums[n - 1 - i] = 5 。
52+
53+
返回使数组 互补 的 最少 操作次数。
54+
55+
## 解题思路
56+
57+
- 这一题考察的是差分数组。通过分析题意,可以得出,针对每一个 `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 的总关系,只需要求一次前缀和即可。
58+
- 这道题要求输出最少的操作次数,所以利用差分数组 + 前缀和,累加前缀和的同时维护最小值。从左往右扫描完一遍以后,输出最小值即可。
59+
60+
## 代码
61+
62+
```go
63+
package leetcode
64+
65+
func minMoves(nums []int, limit int) int {
66+
diff := make([]int, limit*2+2) // nums[i] <= limit, b+limit+1 is maximum limit+limit+1
67+
for j := 0; j < len(nums)/2; j++ {
68+
a, b := min(nums[j], nums[len(nums)-j-1]), max(nums[j], nums[len(nums)-j-1])
69+
// using prefix sum: most interesting point, and is the key to reduce complexity
70+
diff[2] += 2
71+
diff[a+1]--
72+
diff[a+b]--
73+
diff[a+b+1]++
74+
diff[b+limit+1]++
75+
}
76+
cur, res := 0, len(nums)
77+
for i := 2; i <= 2*limit; i++ {
78+
cur += diff[i]
79+
res = min(res, cur)
80+
}
81+
return res
82+
}
83+
84+
func min(a, b int) int {
85+
if a < b {
86+
return a
87+
}
88+
return b
89+
}
90+
91+
func max(a, b int) int {
92+
if a > b {
93+
return a
94+
}
95+
return b
96+
}
97+
```
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package leetcode
2+
3+
// 解法一 优化空间版 DP
4+
func stoneGameVII(stones []int) int {
5+
n := len(stones)
6+
sum := make([]int, n)
7+
dp := make([]int, n)
8+
for i, d := range stones {
9+
sum[i] = d
10+
}
11+
for i := 1; i < n; i++ {
12+
for j := 0; j+i < n; j++ {
13+
if (n-i)%2 == 1 {
14+
d0 := dp[j] + sum[j]
15+
d1 := dp[j+1] + sum[j+1]
16+
if d0 > d1 {
17+
dp[j] = d0
18+
} else {
19+
dp[j] = d1
20+
}
21+
} else {
22+
d0 := dp[j] - sum[j]
23+
d1 := dp[j+1] - sum[j+1]
24+
if d0 < d1 {
25+
dp[j] = d0
26+
} else {
27+
dp[j] = d1
28+
}
29+
}
30+
sum[j] = sum[j] + stones[i+j]
31+
}
32+
}
33+
return dp[0]
34+
}
35+
36+
// 解法二 常规 DP
37+
func stoneGameVII1(stones []int) int {
38+
prefixSum := make([]int, len(stones))
39+
for i := 0; i < len(stones); i++ {
40+
if i == 0 {
41+
prefixSum[i] = stones[i]
42+
} else {
43+
prefixSum[i] = prefixSum[i-1] + stones[i]
44+
}
45+
}
46+
dp := make([][]int, len(stones))
47+
for i := range dp {
48+
dp[i] = make([]int, len(stones))
49+
dp[i][i] = 0
50+
}
51+
n := len(stones)
52+
for l := 2; l <= n; l++ {
53+
for i := 0; i+l <= n; i++ {
54+
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])
55+
}
56+
}
57+
return dp[0][n-1]
58+
}
59+
60+
func max(a, b int) int {
61+
if a > b {
62+
return a
63+
}
64+
return b
65+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package leetcode
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
)
7+
8+
type question1690 struct {
9+
para1690
10+
ans1690
11+
}
12+
13+
// para 是参数
14+
// one 代表第一个参数
15+
type para1690 struct {
16+
stones []int
17+
}
18+
19+
// ans 是答案
20+
// one 代表第一个答案
21+
type ans1690 struct {
22+
one int
23+
}
24+
25+
func Test_Problem1690(t *testing.T) {
26+
27+
qs := []question1690{
28+
29+
{
30+
para1690{[]int{5, 3, 1, 4, 2}},
31+
ans1690{6},
32+
},
33+
34+
{
35+
para1690{[]int{7, 90, 5, 1, 100, 10, 10, 2}},
36+
ans1690{122},
37+
},
38+
}
39+
40+
fmt.Printf("------------------------Leetcode Problem 1690------------------------\n")
41+
42+
for _, q := range qs {
43+
_, p := q.ans1690, q.para1690
44+
fmt.Printf("【input】:%v 【output】:%v\n", p, stoneGameVII(p.stones))
45+
}
46+
fmt.Printf("\n\n\n")
47+
}

0 commit comments

Comments
 (0)