Skip to content

Commit

Permalink
Add solution 1656、1657、1658、1659
Browse files Browse the repository at this point in the history
  • Loading branch information
halfrost committed Nov 22, 2020
1 parent 35c3917 commit 285f7a1
Show file tree
Hide file tree
Showing 9 changed files with 821 additions and 0 deletions.
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
}
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 leetcode/1658.Minimum-Operations-to-Reduce-X-to-Zero/README.md
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 leetcode/1659.Maximize-Grid-Happiness/1659. Maximize Grid Happiness.go
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
}
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")
}
Loading

0 comments on commit 285f7a1

Please sign in to comment.