Skip to content

Commit 285f7a1

Browse files
committed
Add solution 1656、1657、1658、1659
1 parent 35c3917 commit 285f7a1

File tree

9 files changed

+821
-0
lines changed

9 files changed

+821
-0
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package leetcode
2+
3+
func minOperations(nums []int, x int) int {
4+
total := 0
5+
for _, n := range nums {
6+
total += n
7+
}
8+
target := total - x
9+
if target < 0 {
10+
return -1
11+
}
12+
if target == 0 {
13+
return len(nums)
14+
}
15+
left, right, sum, res := 0, 0, 0, -1
16+
for right < len(nums) {
17+
if sum < target {
18+
sum += nums[right]
19+
right++
20+
}
21+
for sum >= target {
22+
if sum == target {
23+
res = max(res, right-left)
24+
}
25+
sum -= nums[left]
26+
left++
27+
}
28+
}
29+
if res == -1 {
30+
return -1
31+
}
32+
return len(nums) - res
33+
}
34+
35+
func max(a, b int) int {
36+
if a > b {
37+
return a
38+
}
39+
return b
40+
}
Lines changed: 53 additions & 0 deletions
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 question1658 struct {
9+
para1658
10+
ans1658
11+
}
12+
13+
// para 是参数
14+
// one 代表第一个参数
15+
type para1658 struct {
16+
nums []int
17+
x int
18+
}
19+
20+
// ans 是答案
21+
// one 代表第一个答案
22+
type ans1658 struct {
23+
one int
24+
}
25+
26+
func Test_Problem1658(t *testing.T) {
27+
28+
qs := []question1658{
29+
30+
{
31+
para1658{[]int{1, 1, 4, 2, 3}, 5},
32+
ans1658{2},
33+
},
34+
35+
{
36+
para1658{[]int{5, 6, 7, 8, 9}, 4},
37+
ans1658{-1},
38+
},
39+
40+
{
41+
para1658{[]int{3, 2, 20, 1, 1, 3}, 10},
42+
ans1658{5},
43+
},
44+
}
45+
46+
fmt.Printf("------------------------Leetcode Problem 1658------------------------\n")
47+
48+
for _, q := range qs {
49+
_, p := q.ans1658, q.para1658
50+
fmt.Printf("【input】:%v 【output】:%v \n", p, minOperations(p.nums, p.x))
51+
}
52+
fmt.Printf("\n\n\n")
53+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# [1658. Minimum Operations to Reduce X to Zero](https://leetcode.com/problems/minimum-operations-to-reduce-x-to-zero/)
2+
3+
4+
## 题目
5+
6+
You are given an integer array `nums` and an integer `x`. In one operation, you can either remove the leftmost or the rightmost element from the array `nums` and subtract its value from `x`. Note that this **modifies** the array for future operations.
7+
8+
Return *the **minimum number** of operations to reduce* `x` *to **exactly*** `0` *if it's possible, otherwise, return* `1`.
9+
10+
**Example 1:**
11+
12+
```
13+
Input: nums = [1,1,4,2,3], x = 5
14+
Output: 2
15+
Explanation: The optimal solution is to remove the last two elements to reduce x to zero.
16+
17+
```
18+
19+
**Example 2:**
20+
21+
```
22+
Input: nums = [5,6,7,8,9], x = 4
23+
Output: -1
24+
25+
```
26+
27+
**Example 3:**
28+
29+
```
30+
Input: nums = [3,2,20,1,1,3], x = 10
31+
Output: 5
32+
Explanation: The optimal solution is to remove the last three elements and the first two elements (5 operations in total) to reduce x to zero.
33+
34+
```
35+
36+
**Constraints:**
37+
38+
- `1 <= nums.length <= 105`
39+
- `1 <= nums[i] <= 104`
40+
- `1 <= x <= 109`
41+
42+
## 题目大意
43+
44+
给你一个整数数组 nums 和一个整数 x 。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。如果可以将 x 恰好 减到 0 ,返回 最小操作数 ;否则,返回 -1 。
45+
46+
## 解题思路
47+
48+
- 给定一个数组 nums 和一个整数 x,要求从数组两端分别移除一些数,使得这些数加起来正好等于整数 x,要求输出最小操作数。
49+
- 要求输出最小操作数,即数组两头的数字个数最少,并且加起来和正好等于整数 x。由于在数组的两头,用 2 个指针分别操作不太方便。我当时解题的时候的思路是把它变成循环数组,这样两边的指针就在一个区间内了。利用滑动窗口找到一个最小的窗口,使得窗口内的累加和等于整数 k。这个方法可行,但是代码挺多的。
50+
- 有没有更优美的方法呢?有的。要想两头的长度最少,也就是中间这段的长度最大。这样就转换成直接在数组上使用滑动窗口求解,累加和等于一个固定值的连续最长的子数组。
51+
- 和这道题类似思路的题目,209,1040(循环数组),325。强烈推荐这 3 题。
52+
53+
## 代码
54+
55+
```go
56+
package leetcode
57+
58+
func minOperations(nums []int, x int) int {
59+
total := 0
60+
for _, n := range nums {
61+
total += n
62+
}
63+
target := total - x
64+
if target < 0 {
65+
return -1
66+
}
67+
if target == 0 {
68+
return len(nums)
69+
}
70+
left, right, sum, res := 0, 0, 0, -1
71+
for right < len(nums) {
72+
if sum < target {
73+
sum += nums[right]
74+
right++
75+
}
76+
for sum >= target {
77+
if sum == target {
78+
res = max(res, right-left)
79+
}
80+
sum -= nums[left]
81+
left++
82+
}
83+
}
84+
if res == -1 {
85+
return -1
86+
}
87+
return len(nums) - res
88+
}
89+
90+
func max(a, b int) int {
91+
if a > b {
92+
return a
93+
}
94+
return b
95+
}
96+
```
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package leetcode
2+
3+
import (
4+
"math"
5+
)
6+
7+
func getMaxGridHappiness(m int, n int, introvertsCount int, extrovertsCount int) int {
8+
// lineStatus 将每一行中 3 种状态进行编码,空白 - 0,内向人 - 1,外向人 - 2,每行状态用三进制表示
9+
// lineStatusList[729][6] 每一行的三进制表示
10+
// introvertsCountInner[729] 每一个 lineStatus 包含的内向人数
11+
// extrovertsCountInner[729] 每一个 lineStatus 包含的外向人数
12+
// scoreInner[729] 每一个 lineStatus 包含的行内得分(只统计 lineStatus 本身的得分,不包括它与上一行的)
13+
// scoreOuter[729][729] 每一个 lineStatus 包含的行外得分
14+
// dp[上一行的 lineStatus][当前处理到的行][剩余的内向人数][剩余的外向人数]
15+
n3, lineStatus, introvertsCountInner, extrovertsCountInner, scoreInner, scoreOuter, lineStatusList, dp := math.Pow(3.0, float64(n)), 0, [729]int{}, [729]int{}, [729]int{}, [729][729]int{}, [729][6]int{}, [729][6][7][7]int{}
16+
for i := 0; i < 729; i++ {
17+
lineStatusList[i] = [6]int{}
18+
}
19+
for i := 0; i < 729; i++ {
20+
dp[i] = [6][7][7]int{}
21+
for j := 0; j < 6; j++ {
22+
dp[i][j] = [7][7]int{}
23+
for k := 0; k < 7; k++ {
24+
dp[i][j][k] = [7]int{-1, -1, -1, -1, -1, -1, -1}
25+
}
26+
}
27+
}
28+
// 预处理
29+
for lineStatus = 0; lineStatus < int(n3); lineStatus++ {
30+
tmp := lineStatus
31+
for i := 0; i < n; i++ {
32+
lineStatusList[lineStatus][i] = tmp % 3
33+
tmp /= 3
34+
}
35+
introvertsCountInner[lineStatus], extrovertsCountInner[lineStatus], scoreInner[lineStatus] = 0, 0, 0
36+
for i := 0; i < n; i++ {
37+
if lineStatusList[lineStatus][i] != 0 {
38+
// 个人分数
39+
if lineStatusList[lineStatus][i] == 1 {
40+
introvertsCountInner[lineStatus]++
41+
scoreInner[lineStatus] += 120
42+
} else if lineStatusList[lineStatus][i] == 2 {
43+
extrovertsCountInner[lineStatus]++
44+
scoreInner[lineStatus] += 40
45+
}
46+
// 行内分数
47+
if i-1 >= 0 {
48+
scoreInner[lineStatus] += closeScore(lineStatusList[lineStatus][i], lineStatusList[lineStatus][i-1])
49+
}
50+
}
51+
}
52+
}
53+
// 行外分数
54+
for lineStatus0 := 0; lineStatus0 < int(n3); lineStatus0++ {
55+
for lineStatus1 := 0; lineStatus1 < int(n3); lineStatus1++ {
56+
scoreOuter[lineStatus0][lineStatus1] = 0
57+
for i := 0; i < n; i++ {
58+
scoreOuter[lineStatus0][lineStatus1] += closeScore(lineStatusList[lineStatus0][i], lineStatusList[lineStatus1][i])
59+
}
60+
}
61+
}
62+
return dfs(0, 0, introvertsCount, extrovertsCount, m, int(n3), &dp, &introvertsCountInner, &extrovertsCountInner, &scoreInner, &scoreOuter)
63+
}
64+
65+
// 如果 x 和 y 相邻,需要加上的分数
66+
func closeScore(x, y int) int {
67+
if x == 0 || y == 0 {
68+
return 0
69+
}
70+
// 两个内向的人,每个人要 -30,一共 -60
71+
if x == 1 && y == 1 {
72+
return -60
73+
}
74+
if x == 2 && y == 2 {
75+
return 40
76+
}
77+
return -10
78+
}
79+
80+
// dfs(上一行的 lineStatus,当前处理到的行,剩余的内向人数,剩余的外向人数)
81+
func dfs(lineStatusLast, row, introvertsCount, extrovertsCount, m, n3 int, dp *[729][6][7][7]int, introvertsCountInner, extrovertsCountInner, scoreInner *[729]int, scoreOuter *[729][729]int) int {
82+
// 边界条件:如果已经处理完,或者没有人了
83+
if row == m || introvertsCount+extrovertsCount == 0 {
84+
return 0
85+
}
86+
// 记忆化
87+
if dp[lineStatusLast][row][introvertsCount][extrovertsCount] != -1 {
88+
return dp[lineStatusLast][row][introvertsCount][extrovertsCount]
89+
}
90+
best := 0
91+
for lineStatus := 0; lineStatus < n3; lineStatus++ {
92+
if introvertsCountInner[lineStatus] > introvertsCount || extrovertsCountInner[lineStatus] > extrovertsCount {
93+
continue
94+
}
95+
score := scoreInner[lineStatus] + scoreOuter[lineStatus][lineStatusLast]
96+
best = max(best, score+dfs(lineStatus, row+1, introvertsCount-introvertsCountInner[lineStatus], extrovertsCount-extrovertsCountInner[lineStatus], m, n3, dp, introvertsCountInner, extrovertsCountInner, scoreInner, scoreOuter))
97+
}
98+
dp[lineStatusLast][row][introvertsCount][extrovertsCount] = best
99+
return best
100+
}
101+
102+
func max(a int, b int) int {
103+
if a > b {
104+
return a
105+
}
106+
return b
107+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package leetcode
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
)
7+
8+
type question1659 struct {
9+
para1659
10+
ans1659
11+
}
12+
13+
// para 是参数
14+
// one 代表第一个参数
15+
type para1659 struct {
16+
m int
17+
n int
18+
introvertsCount int
19+
extrovertsCount int
20+
}
21+
22+
// ans 是答案
23+
// one 代表第一个答案
24+
type ans1659 struct {
25+
one int
26+
}
27+
28+
func Test_Problem1659(t *testing.T) {
29+
30+
qs := []question1659{
31+
32+
{
33+
para1659{2, 3, 1, 2},
34+
ans1659{240},
35+
},
36+
37+
{
38+
para1659{3, 1, 2, 1},
39+
ans1659{260},
40+
},
41+
42+
{
43+
para1659{2, 2, 4, 0},
44+
ans1659{240},
45+
},
46+
}
47+
48+
fmt.Printf("------------------------Leetcode Problem 1659------------------------\n")
49+
50+
for _, q := range qs {
51+
_, p := q.ans1659, q.para1659
52+
fmt.Printf("【input】:%v 【output】:%v \n", p, getMaxGridHappiness(p.m, p.n, p.introvertsCount, p.extrovertsCount))
53+
}
54+
fmt.Printf("\n\n\n")
55+
}

0 commit comments

Comments
 (0)