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
821 additions
and
0 deletions.
There are no files selected for viewing
40 changes: 40 additions & 0 deletions
40
...58.Minimum-Operations-to-Reduce-X-to-Zero/1658. Minimum Operations to Reduce X to Zero.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,40 @@ | ||
package leetcode | ||
|
||
func minOperations(nums []int, x int) int { | ||
total := 0 | ||
for _, n := range nums { | ||
total += n | ||
} | ||
target := total - x | ||
if target < 0 { | ||
return -1 | ||
} | ||
if target == 0 { | ||
return len(nums) | ||
} | ||
left, right, sum, res := 0, 0, 0, -1 | ||
for right < len(nums) { | ||
if sum < target { | ||
sum += nums[right] | ||
right++ | ||
} | ||
for sum >= target { | ||
if sum == target { | ||
res = max(res, right-left) | ||
} | ||
sum -= nums[left] | ||
left++ | ||
} | ||
} | ||
if res == -1 { | ||
return -1 | ||
} | ||
return len(nums) - res | ||
} | ||
|
||
func max(a, b int) int { | ||
if a > b { | ||
return a | ||
} | ||
return b | ||
} |
53 changes: 53 additions & 0 deletions
53
...nimum-Operations-to-Reduce-X-to-Zero/1658. Minimum Operations to Reduce X to Zero_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 question1658 struct { | ||
para1658 | ||
ans1658 | ||
} | ||
|
||
// para 是参数 | ||
// one 代表第一个参数 | ||
type para1658 struct { | ||
nums []int | ||
x int | ||
} | ||
|
||
// ans 是答案 | ||
// one 代表第一个答案 | ||
type ans1658 struct { | ||
one int | ||
} | ||
|
||
func Test_Problem1658(t *testing.T) { | ||
|
||
qs := []question1658{ | ||
|
||
{ | ||
para1658{[]int{1, 1, 4, 2, 3}, 5}, | ||
ans1658{2}, | ||
}, | ||
|
||
{ | ||
para1658{[]int{5, 6, 7, 8, 9}, 4}, | ||
ans1658{-1}, | ||
}, | ||
|
||
{ | ||
para1658{[]int{3, 2, 20, 1, 1, 3}, 10}, | ||
ans1658{5}, | ||
}, | ||
} | ||
|
||
fmt.Printf("------------------------Leetcode Problem 1658------------------------\n") | ||
|
||
for _, q := range qs { | ||
_, p := q.ans1658, q.para1658 | ||
fmt.Printf("【input】:%v 【output】:%v \n", p, minOperations(p.nums, p.x)) | ||
} | ||
fmt.Printf("\n\n\n") | ||
} |
96 changes: 96 additions & 0 deletions
96
leetcode/1658.Minimum-Operations-to-Reduce-X-to-Zero/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,96 @@ | ||
# [1658. Minimum Operations to Reduce X to Zero](https://leetcode.com/problems/minimum-operations-to-reduce-x-to-zero/) | ||
|
||
|
||
## 题目 | ||
|
||
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. | ||
|
||
Return *the **minimum number** of operations to reduce* `x` *to **exactly*** `0` *if it's possible, otherwise, return* `1`. | ||
|
||
**Example 1:** | ||
|
||
``` | ||
Input: nums = [1,1,4,2,3], x = 5 | ||
Output: 2 | ||
Explanation: The optimal solution is to remove the last two elements to reduce x to zero. | ||
``` | ||
|
||
**Example 2:** | ||
|
||
``` | ||
Input: nums = [5,6,7,8,9], x = 4 | ||
Output: -1 | ||
``` | ||
|
||
**Example 3:** | ||
|
||
``` | ||
Input: nums = [3,2,20,1,1,3], x = 10 | ||
Output: 5 | ||
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. | ||
``` | ||
|
||
**Constraints:** | ||
|
||
- `1 <= nums.length <= 105` | ||
- `1 <= nums[i] <= 104` | ||
- `1 <= x <= 109` | ||
|
||
## 题目大意 | ||
|
||
给你一个整数数组 nums 和一个整数 x 。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。如果可以将 x 恰好 减到 0 ,返回 最小操作数 ;否则,返回 -1 。 | ||
|
||
## 解题思路 | ||
|
||
- 给定一个数组 nums 和一个整数 x,要求从数组两端分别移除一些数,使得这些数加起来正好等于整数 x,要求输出最小操作数。 | ||
- 要求输出最小操作数,即数组两头的数字个数最少,并且加起来和正好等于整数 x。由于在数组的两头,用 2 个指针分别操作不太方便。我当时解题的时候的思路是把它变成循环数组,这样两边的指针就在一个区间内了。利用滑动窗口找到一个最小的窗口,使得窗口内的累加和等于整数 k。这个方法可行,但是代码挺多的。 | ||
- 有没有更优美的方法呢?有的。要想两头的长度最少,也就是中间这段的长度最大。这样就转换成直接在数组上使用滑动窗口求解,累加和等于一个固定值的连续最长的子数组。 | ||
- 和这道题类似思路的题目,209,1040(循环数组),325。强烈推荐这 3 题。 | ||
|
||
## 代码 | ||
|
||
```go | ||
package leetcode | ||
|
||
func minOperations(nums []int, x int) int { | ||
total := 0 | ||
for _, n := range nums { | ||
total += n | ||
} | ||
target := total - x | ||
if target < 0 { | ||
return -1 | ||
} | ||
if target == 0 { | ||
return len(nums) | ||
} | ||
left, right, sum, res := 0, 0, 0, -1 | ||
for right < len(nums) { | ||
if sum < target { | ||
sum += nums[right] | ||
right++ | ||
} | ||
for sum >= target { | ||
if sum == target { | ||
res = max(res, right-left) | ||
} | ||
sum -= nums[left] | ||
left++ | ||
} | ||
} | ||
if res == -1 { | ||
return -1 | ||
} | ||
return len(nums) - res | ||
} | ||
|
||
func max(a, b int) int { | ||
if a > b { | ||
return a | ||
} | ||
return b | ||
} | ||
``` |
107 changes: 107 additions & 0 deletions
107
leetcode/1659.Maximize-Grid-Happiness/1659. Maximize Grid Happiness.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,107 @@ | ||
package leetcode | ||
|
||
import ( | ||
"math" | ||
) | ||
|
||
func getMaxGridHappiness(m int, n int, introvertsCount int, extrovertsCount int) int { | ||
// lineStatus 将每一行中 3 种状态进行编码,空白 - 0,内向人 - 1,外向人 - 2,每行状态用三进制表示 | ||
// lineStatusList[729][6] 每一行的三进制表示 | ||
// introvertsCountInner[729] 每一个 lineStatus 包含的内向人数 | ||
// extrovertsCountInner[729] 每一个 lineStatus 包含的外向人数 | ||
// scoreInner[729] 每一个 lineStatus 包含的行内得分(只统计 lineStatus 本身的得分,不包括它与上一行的) | ||
// scoreOuter[729][729] 每一个 lineStatus 包含的行外得分 | ||
// dp[上一行的 lineStatus][当前处理到的行][剩余的内向人数][剩余的外向人数] | ||
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{} | ||
for i := 0; i < 729; i++ { | ||
lineStatusList[i] = [6]int{} | ||
} | ||
for i := 0; i < 729; i++ { | ||
dp[i] = [6][7][7]int{} | ||
for j := 0; j < 6; j++ { | ||
dp[i][j] = [7][7]int{} | ||
for k := 0; k < 7; k++ { | ||
dp[i][j][k] = [7]int{-1, -1, -1, -1, -1, -1, -1} | ||
} | ||
} | ||
} | ||
// 预处理 | ||
for lineStatus = 0; lineStatus < int(n3); lineStatus++ { | ||
tmp := lineStatus | ||
for i := 0; i < n; i++ { | ||
lineStatusList[lineStatus][i] = tmp % 3 | ||
tmp /= 3 | ||
} | ||
introvertsCountInner[lineStatus], extrovertsCountInner[lineStatus], scoreInner[lineStatus] = 0, 0, 0 | ||
for i := 0; i < n; i++ { | ||
if lineStatusList[lineStatus][i] != 0 { | ||
// 个人分数 | ||
if lineStatusList[lineStatus][i] == 1 { | ||
introvertsCountInner[lineStatus]++ | ||
scoreInner[lineStatus] += 120 | ||
} else if lineStatusList[lineStatus][i] == 2 { | ||
extrovertsCountInner[lineStatus]++ | ||
scoreInner[lineStatus] += 40 | ||
} | ||
// 行内分数 | ||
if i-1 >= 0 { | ||
scoreInner[lineStatus] += closeScore(lineStatusList[lineStatus][i], lineStatusList[lineStatus][i-1]) | ||
} | ||
} | ||
} | ||
} | ||
// 行外分数 | ||
for lineStatus0 := 0; lineStatus0 < int(n3); lineStatus0++ { | ||
for lineStatus1 := 0; lineStatus1 < int(n3); lineStatus1++ { | ||
scoreOuter[lineStatus0][lineStatus1] = 0 | ||
for i := 0; i < n; i++ { | ||
scoreOuter[lineStatus0][lineStatus1] += closeScore(lineStatusList[lineStatus0][i], lineStatusList[lineStatus1][i]) | ||
} | ||
} | ||
} | ||
return dfs(0, 0, introvertsCount, extrovertsCount, m, int(n3), &dp, &introvertsCountInner, &extrovertsCountInner, &scoreInner, &scoreOuter) | ||
} | ||
|
||
// 如果 x 和 y 相邻,需要加上的分数 | ||
func closeScore(x, y int) int { | ||
if x == 0 || y == 0 { | ||
return 0 | ||
} | ||
// 两个内向的人,每个人要 -30,一共 -60 | ||
if x == 1 && y == 1 { | ||
return -60 | ||
} | ||
if x == 2 && y == 2 { | ||
return 40 | ||
} | ||
return -10 | ||
} | ||
|
||
// dfs(上一行的 lineStatus,当前处理到的行,剩余的内向人数,剩余的外向人数) | ||
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 { | ||
// 边界条件:如果已经处理完,或者没有人了 | ||
if row == m || introvertsCount+extrovertsCount == 0 { | ||
return 0 | ||
} | ||
// 记忆化 | ||
if dp[lineStatusLast][row][introvertsCount][extrovertsCount] != -1 { | ||
return dp[lineStatusLast][row][introvertsCount][extrovertsCount] | ||
} | ||
best := 0 | ||
for lineStatus := 0; lineStatus < n3; lineStatus++ { | ||
if introvertsCountInner[lineStatus] > introvertsCount || extrovertsCountInner[lineStatus] > extrovertsCount { | ||
continue | ||
} | ||
score := scoreInner[lineStatus] + scoreOuter[lineStatus][lineStatusLast] | ||
best = max(best, score+dfs(lineStatus, row+1, introvertsCount-introvertsCountInner[lineStatus], extrovertsCount-extrovertsCountInner[lineStatus], m, n3, dp, introvertsCountInner, extrovertsCountInner, scoreInner, scoreOuter)) | ||
} | ||
dp[lineStatusLast][row][introvertsCount][extrovertsCount] = best | ||
return best | ||
} | ||
|
||
func max(a int, b int) int { | ||
if a > b { | ||
return a | ||
} | ||
return b | ||
} |
55 changes: 55 additions & 0 deletions
55
leetcode/1659.Maximize-Grid-Happiness/1659. Maximize Grid Happiness_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,55 @@ | ||
package leetcode | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
) | ||
|
||
type question1659 struct { | ||
para1659 | ||
ans1659 | ||
} | ||
|
||
// para 是参数 | ||
// one 代表第一个参数 | ||
type para1659 struct { | ||
m int | ||
n int | ||
introvertsCount int | ||
extrovertsCount int | ||
} | ||
|
||
// ans 是答案 | ||
// one 代表第一个答案 | ||
type ans1659 struct { | ||
one int | ||
} | ||
|
||
func Test_Problem1659(t *testing.T) { | ||
|
||
qs := []question1659{ | ||
|
||
{ | ||
para1659{2, 3, 1, 2}, | ||
ans1659{240}, | ||
}, | ||
|
||
{ | ||
para1659{3, 1, 2, 1}, | ||
ans1659{260}, | ||
}, | ||
|
||
{ | ||
para1659{2, 2, 4, 0}, | ||
ans1659{240}, | ||
}, | ||
} | ||
|
||
fmt.Printf("------------------------Leetcode Problem 1659------------------------\n") | ||
|
||
for _, q := range qs { | ||
_, p := q.ans1659, q.para1659 | ||
fmt.Printf("【input】:%v 【output】:%v \n", p, getMaxGridHappiness(p.m, p.n, p.introvertsCount, p.extrovertsCount)) | ||
} | ||
fmt.Printf("\n\n\n") | ||
} |
Oops, something went wrong.