Merge pull request #34 from halfrost/add_hugo

Add hugo
This commit is contained in:
halfrost
2020-08-07 15:30:14 +08:00
committed by GitHub
604 changed files with 51508 additions and 1999 deletions

View File

@@ -4,6 +4,7 @@ on:
push:
branches:
- master # 只在master上push触发部署
- add_hugo
paths-ignore: # 下列文件的变更不触发部署,可以自行添加
- README.md
- LICENSE

View File

@@ -0,0 +1,26 @@
package leetcode
func canJump(nums []int) bool {
n := len(nums)
if n == 0 {
return false
}
if n == 1 {
return true
}
maxJump := 0
for i, v := range nums {
if i > maxJump {
return false
}
maxJump = max(maxJump, i+v)
}
return true
}
func max(a int, b int) int {
if a > b {
return a
}
return b
}

View File

@@ -0,0 +1,46 @@
package leetcode
import (
"fmt"
"testing"
)
type question55 struct {
para55
ans55
}
// para 是参数
// one 代表第一个参数
type para55 struct {
one []int
}
// ans 是答案
// one 代表第一个答案
type ans55 struct {
one bool
}
func Test_Problem55(t *testing.T) {
qs := []question55{
question55{
para55{[]int{2, 3, 1, 1, 4}},
ans55{true},
},
question55{
para55{[]int{3, 2, 1, 0, 4}},
ans55{false},
},
}
fmt.Printf("------------------------Leetcode Problem 55------------------------\n")
for _, q := range qs {
_, p := q.ans55, q.para55
fmt.Printf("【input】:%v 【output】:%v\n", p, canJump(p.one))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,58 @@
# 55. Jump Game
## 题目
Given an array of non-negative integers, you are initially positioned at the first index of the array.
Each element in the array represents your maximum jump length at that position.
Determine if you are able to reach the last index.
**Example 1**:
```
Input: [2,3,1,1,4]
Output: true
Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.
```
**Example 2**:
```
Input: [3,2,1,0,4]
Output: false
Explanation: You will always arrive at index 3 no matter what. Its maximum
jump length is 0, which makes it impossible to reach the last index.
```
## 题目大意
给定一个非负整数数组,最初位于数组的第一个位置。数组中的每个元素代表在该位置可以跳跃的最大长度。判断是否能够到达最后一个位置。
## 解题思路
- 给出一个非负数组,要求判断从数组 0 下标开始,能否到达数组最后一个位置。
- 这一题比较简单。如果某一个作为 `起跳点` 的格子可以跳跃的距离是 `n`,那么表示后面 `n` 个格子都可以作为 `起跳点`。可以对每一个能作为 `起跳点` 的格子都尝试跳一次,把 `能跳到最远的距离maxJump` 不断更新。如果可以一直跳到最后,就成功了。如果中间有一个点比 `maxJump` 还要大,说明在这个点和 maxJump 中间连不上了,有些点不能到达最后一个位置。
## 代码
```go
func canJump(nums []int) bool {
n := len(nums)
if n == 0 {
return false
}
if n == 1 {
return true
}
maxJump := 0
for i, v := range nums {
if i > maxJump {
return false
}
maxJump = max(maxJump, i+v)
}
return true
}
```

View File

@@ -0,0 +1,41 @@
package leetcode
import (
"github.com/halfrost/LeetCode-Go/structures"
)
// TreeNode define
type TreeNode = structures.TreeNode
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func rob337(root *TreeNode) int {
a, b := dfsTreeRob(root)
return max(a, b)
}
func dfsTreeRob(root *TreeNode) (a, b int) {
if root == nil {
return 0, 0
}
l0, l1 := dfsTreeRob(root.Left)
r0, r1 := dfsTreeRob(root.Right)
// 当前节点没有被打劫
tmp0 := max(l0, l1) + max(r0, r1)
// 当前节点被打劫
tmp1 := root.Val + l0 + r0
return tmp0, tmp1
}
func max(a int, b int) int {
if a > b {
return a
}
return b
}

View File

@@ -0,0 +1,54 @@
package leetcode
import (
"fmt"
"testing"
"github.com/halfrost/LeetCode-Go/structures"
)
type question337 struct {
para337
ans337
}
// para 是参数
// one 代表第一个参数
type para337 struct {
one []int
}
// ans 是答案
// one 代表第一个答案
type ans337 struct {
one int
}
func Test_Problem337(t *testing.T) {
qs := []question337{
question337{
para337{[]int{3, 2, 3, structures.NULL, 3, structures.NULL, 1}},
ans337{7},
},
question337{
para337{[]int{}},
ans337{0},
},
question337{
para337{[]int{3, 4, 5, 1, 3, structures.NULL, 1}},
ans337{9},
},
}
fmt.Printf("------------------------Leetcode Problem 337------------------------\n")
for _, q := range qs {
_, p := q.ans337, q.para337
fmt.Printf("【input】:%v 【output】:%v\n", p, rob337(structures.Ints2TreeNode(p.one)))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,72 @@
# 337. House Robber III
## 题目
The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the "root." Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that "all houses in this place forms a binary tree". It will automatically contact the police if two directly-linked houses were broken into on the same night.
Determine the maximum amount of money the thief can rob tonight without alerting the police.
**Example 1**:
```
Input: [3,2,3,null,3,null,1]
3
/ \
2 3
\ \
3 1
Output: 7
Explanation: Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.
```
**Example 2**:
```
Input: [3,4,5,1,3,null,1]
3
/ \
4 5
/ \ \
1 3 1
Output: 9
Explanation: Maximum amount of money the thief can rob = 4 + 5 = 9.
```
## 题目大意
一个新的可行窃的地区只有一个入口,称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。
## 解题思路
- 这一题是打家劫舍的第 3 题。这一题需要偷的房子是树状的。报警的条件还是相邻的房子如果都被偷了,就会触发报警。只不过这里相邻的房子是树上的。问小偷在不触发报警的条件下最终能偷的最高金额。
- 解题思路是 DFS。当前节点是否被打劫,会产生 2 种结果。如果当前节点被打劫,那么它的孩子节点可以被打劫;如果当前节点没有被打劫,那么它的孩子节点不能被打劫。按照这个逻辑递归,最终递归到根节点,取最大值输出即可。
## 代码
```go
func rob337(root *TreeNode) int {
a, b := dfsTreeRob(root)
return max(a, b)
}
func dfsTreeRob(root *TreeNode) (a, b int) {
if root == nil {
return 0, 0
}
l0, l1 := dfsTreeRob(root.Left)
r0, r1 := dfsTreeRob(root.Right)
// 当前节点没有被打劫
tmp0 := max(l0, l1) + max(r0, r1)
// 当前节点被打劫
tmp1 := root.Val + l0 + r0
return tmp0, tmp1
}
```

View File

@@ -0,0 +1,49 @@
package leetcode
// 解法一 DP
func findTargetSumWays(nums []int, S int) int {
total := 0
for _, n := range nums {
total += n
}
if S > total || (S+total)%2 == 1 {
return 0
}
target := (S + total) / 2
dp := make([]int, target+1)
dp[0] = 1
for _, n := range nums {
for i := target; i >= n; i-- {
dp[i] += dp[i-n]
}
}
return dp[target]
}
// 解法二 DFS
func findTargetSumWays1(nums []int, S int) int {
// sums[i] 存储的是后缀和 nums[i:],即从 i 到结尾的和
sums := make([]int, len(nums))
sums[len(nums)-1] = nums[len(nums)-1]
for i := len(nums) - 2; i > -1; i-- {
sums[i] = sums[i+1] + nums[i]
}
res := 0
dfsFindTargetSumWays(nums, 0, 0, S, &res, sums)
return res
}
func dfsFindTargetSumWays(nums []int, index int, curSum int, S int, res *int, sums []int) {
if index == len(nums) {
if curSum == S {
*(res) = *(res) + 1
}
return
}
// 剪枝优化:如果 sums[index] 值小于剩下需要正数的值,那么右边就算都是 + 号也无能为力了,所以这里可以剪枝了
if S-curSum > sums[index] {
return
}
dfsFindTargetSumWays(nums, index+1, curSum+nums[index], S, res, sums)
dfsFindTargetSumWays(nums, index+1, curSum-nums[index], S, res, sums)
}

View File

@@ -0,0 +1,43 @@
package leetcode
import (
"fmt"
"testing"
)
type question494 struct {
para494
ans494
}
// para 是参数
// one 代表第一个参数
type para494 struct {
nums []int
S int
}
// ans 是答案
// one 代表第一个答案
type ans494 struct {
one int
}
func Test_Problem494(t *testing.T) {
qs := []question494{
question494{
para494{[]int{1, 1, 1, 1, 1}, 3},
ans494{5},
},
}
fmt.Printf("------------------------Leetcode Problem 494------------------------\n")
for _, q := range qs {
_, p := q.ans494, q.para494
fmt.Printf("【input】:%v 【output】:%v\n", p, findTargetSumWays(p.nums, p.S))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,107 @@
# 494. Target Sum
## 题目
You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symbols `+` and `-`. For each integer, you should choose one from `+` and `-` as its new symbol.
Find out how many ways to assign symbols to make sum of integers equal to target S.
**Example 1**:
```
Input: nums is [1, 1, 1, 1, 1], S is 3.
Output: 5
Explanation:
-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3
There are 5 ways to assign symbols to make the sum of nums be target 3.
```
**Note**:
1. The length of the given array is positive and will not exceed 20.
2. The sum of elements in the given array will not exceed 1000.
3. Your output answer is guaranteed to be fitted in a 32-bit integer.
## 题目大意
给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S。现在有两个符号 + 和 -。对于数组中的任意一个整数,可以从 + 或 - 中选择一个符号添加在前面。返回可以使最终数组和为目标数 S 的所有添加符号的方法数。
提示:
- 数组非空,且长度不会超过 20 。
- 初始的数组的和不会超过 1000 。
- 保证返回的最终结果能被 32 位整数存下。
## 解题思路
- 给出一个数组,要求在这个数组里面的每个元素前面加上 + 或者 - 号,最终总和等于 S。问有多少种不同的方法。
- 这一题可以用 DP 和 DFS 解答。DFS 方法就不比较暴力简单了。见代码。这里分析一下 DP 的做法。题目要求在数组元素前加上 + 或者 - 号,其实相当于把数组分成了 2 组,一组全部都加 + 号,一组都加 - 号。记 + 号的一组 P ,记 - 号的一组 N,那么可以推出以下的关系。
```go
sum(P) - sum(N) = target
sum(P) + sum(N) + sum(P) - sum(N) = target + sum(P) + sum(N)
2 * sum(P) = target + sum(nums)
```
等号两边都加上 `sum(N) + sum(P)`,于是可以得到结果 `2 * sum(P) = target + sum(nums)`,那么这道题就转换成了,能否在数组中找到这样一个集合,和等于 `(target + sum(nums)) / 2`。那么这题就转化为了第 416 题了。`dp[i]` 中存储的是能使和为 `i` 的方法个数。
- 如果和不是偶数,即不能被 2 整除,那说明找不到满足题目要求的解了,直接输出 0 。
## 代码
```go
func findTargetSumWays(nums []int, S int) int {
total := 0
for _, n := range nums {
total += n
}
if S > total || (S+total)%2 == 1 {
return 0
}
target := (S + total) / 2
dp := make([]int, target+1)
dp[0] = 1
for _, n := range nums {
for i := target; i >= n; i-- {
dp[i] += dp[i-n]
}
}
return dp[target]
}
// 解法二 DFS
func findTargetSumWays1(nums []int, S int) int {
// sums[i] 存储的是后缀和 nums[i:],即从 i 到结尾的和
sums := make([]int, len(nums))
sums[len(nums)-1] = nums[len(nums)-1]
for i := len(nums) - 2; i > -1; i-- {
sums[i] = sums[i+1] + nums[i]
}
res := 0
dfsFindTargetSumWays(nums, 0, 0, S, &res, sums)
return res
}
func dfsFindTargetSumWays(nums []int, index int, curSum int, S int, res *int, sums []int) {
if index == len(nums) {
if curSum == S {
*(res) = *(res) + 1
}
return
}
// 剪枝优化:如果 sums[index] 值小于剩下需要正数的值,那么右边就算都是 + 号也无能为力了,所以这里可以剪枝了
if S-curSum > sums[index] {
return
}
dfsFindTargetSumWays(nums, index+1, curSum+nums[index], S, res, sums)
dfsFindTargetSumWays(nums, index+1, curSum-nums[index], S, res, sums)
}
```

View File

@@ -0,0 +1,63 @@
package leetcode
var dir8 = [][]int{
[]int{-1, -1},
[]int{-1, 0},
[]int{-1, 1},
[]int{0, 1},
[]int{1, 1},
[]int{1, 0},
[]int{1, -1},
[]int{0, -1},
}
func updateBoard(board [][]byte, click []int) [][]byte {
if board[click[0]][click[1]] == 'M' {
board[click[0]][click[1]] = 'X'
return board
}
mineMap := make([][]int, len(board))
for i := range board {
mineMap[i] = make([]int, len(board[i]))
}
for i := range board {
for j := range board[i] {
if board[i][j] == 'M' {
mineMap[i][j] = -1
for _, d := range dir8 {
nx, ny := i+d[0], j+d[1]
if isInBoard(board, nx, ny) && mineMap[nx][ny] >= 0 {
mineMap[nx][ny]++
}
}
}
}
}
mineSweeper(click[0], click[1], board, mineMap, dir8)
return board
}
func isInBoard(board [][]byte, x, y int) bool {
return x >= 0 && x < len(board) && y >= 0 && y < len(board[0])
}
func mineSweeper(x, y int, board [][]byte, mineMap [][]int, dir8 [][]int) {
if board[x][y] != 'M' && board[x][y] != 'E' {
return
}
if mineMap[x][y] == -1 {
board[x][y] = 'X'
} else if mineMap[x][y] > 0 {
board[x][y] = '0' + byte(mineMap[x][y])
} else {
board[x][y] = 'B'
for _, d := range dir8 {
nx, ny := x+d[0], y+d[1]
if isInBoard(board, nx, ny) && mineMap[nx][ny] >= 0 {
mineSweeper(nx, ny, board, mineMap, dir8)
}
}
}
}

View File

@@ -0,0 +1,68 @@
package leetcode
import (
"fmt"
"testing"
)
type question529 struct {
para529
ans529
}
// para 是参数
// one 代表第一个参数
type para529 struct {
b [][]byte
click []int
}
// ans 是答案
// one 代表第一个答案
type ans529 struct {
one [][]byte
}
func Test_Problem529(t *testing.T) {
qs := []question529{
question529{
para529{[][]byte{
[]byte{'E', 'E', 'E', 'E', 'E'},
[]byte{'E', 'E', 'M', 'E', 'E'},
[]byte{'E', 'E', 'E', 'E', 'E'},
[]byte{'E', 'E', 'E', 'E', 'E'},
}, []int{3, 0}},
ans529{[][]byte{
[]byte{'B', '1', 'E', '1', 'B'},
[]byte{'B', '1', 'M', '1', 'B'},
[]byte{'B', '1', '1', '1', 'B'},
[]byte{'B', 'B', 'B', 'B', 'B'},
}},
},
question529{
para529{[][]byte{
[]byte{'B', '1', 'E', '1', 'B'},
[]byte{'B', '1', 'M', '1', 'B'},
[]byte{'B', '1', '1', '1', 'B'},
[]byte{'B', 'B', 'B', 'B', 'B'},
}, []int{1, 2}},
ans529{[][]byte{
[]byte{'B', '1', 'E', '1', 'B'},
[]byte{'B', '1', 'X', '1', 'B'},
[]byte{'B', '1', '1', '1', 'B'},
[]byte{'B', 'B', 'B', 'B', 'B'},
}},
},
}
fmt.Printf("------------------------Leetcode Problem 529------------------------\n")
for _, q := range qs {
_, p := q.ans529, q.para529
fmt.Printf("【input】:%v 【output】:%v\n\n\n", p, updateBoard(p.b, p.click))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,144 @@
# 529. Minesweeper
## 题目
Let's play the minesweeper game ([Wikipedia](https://en.wikipedia.org/wiki/Minesweeper_(video_game)), [online game](http://minesweeperonline.com/))!
You are given a 2D char matrix representing the game board. **'M'** represents an **unrevealed** mine, **'E'** represents an **unrevealed** empty square, **'B'** represents a **revealed** blank square that has no adjacent (above, below, left, right, and all 4 diagonals) mines, **digit** ('1' to '8') represents how many mines are adjacent to this **revealed** square, and finally **'X'** represents a **revealed** mine.
Now given the next click position (row and column indices) among all the **unrevealed** squares ('M' or 'E'), return the board after revealing this position according to the following rules:
1. If a mine ('M') is revealed, then the game is over - change it to **'X'**.
2. If an empty square ('E') with **no adjacent mines** is revealed, then change it to revealed blank ('B') and all of its adjacent **unrevealed** squares should be revealed recursively.
3. If an empty square ('E') with **at least one adjacent mine** is revealed, then change it to a digit ('1' to '8') representing the number of adjacent mines.
4. Return the board when no more squares will be revealed.
**Example 1**:
```
Input:
[['E', 'E', 'E', 'E', 'E'],
['E', 'E', 'M', 'E', 'E'],
['E', 'E', 'E', 'E', 'E'],
['E', 'E', 'E', 'E', 'E']]
Click : [3,0]
Output:
[['B', '1', 'E', '1', 'B'],
['B', '1', 'M', '1', 'B'],
['B', '1', '1', '1', 'B'],
['B', 'B', 'B', 'B', 'B']]
Explanation:
```
![https://assets.leetcode.com/uploads/2018/10/12/minesweeper_example_1.png](https://assets.leetcode.com/uploads/2018/10/12/minesweeper_example_1.png)
**Example 2**:
```
Input:
[['B', '1', 'E', '1', 'B'],
['B', '1', 'M', '1', 'B'],
['B', '1', '1', '1', 'B'],
['B', 'B', 'B', 'B', 'B']]
Click : [1,2]
Output:
[['B', '1', 'E', '1', 'B'],
['B', '1', 'X', '1', 'B'],
['B', '1', '1', '1', 'B'],
['B', 'B', 'B', 'B', 'B']]
Explanation:
```
![https://assets.leetcode.com/uploads/2018/10/12/minesweeper_example_2.png](https://assets.leetcode.com/uploads/2018/10/12/minesweeper_example_2.png)
**Note**:
1. The range of the input matrix's height and width is [1,50].
2. The click position will only be an unrevealed square ('M' or 'E'), which also means the input board contains at least one clickable square.
3. The input board won't be a stage when game is over (some mines have been revealed).
4. For simplicity, not mentioned rules should be ignored in this problem. For example, you **don't** need to reveal all the unrevealed mines when the game is over, consider any cases that you will win the game or flag any squares.
## 题目大意
给定一个代表游戏板的二维字符矩阵。 'M' 代表一个未挖出的地雷,'E' 代表一个未挖出的空方块,'B' 代表没有相邻(上,下,左,右,和所有4个对角线)地雷的已挖出的空白方块,数字('1' 到 '8')表示有多少地雷与这块已挖出的方块相邻,'X' 则表示一个已挖出的地雷。现在给出在所有未挖出的方块中('M'或者'E')的下一个点击位置(行和列索引),根据以下规则,返回相应位置被点击后对应的面板:
1. 如果一个地雷('M')被挖出,游戏就结束了- 把它改为 'X'。
2. 如果一个没有相邻地雷的空方块('E')被挖出,修改它为('B'),并且所有和其相邻的未挖出方块都应该被递归地揭露。
3. 如果一个至少与一个地雷相邻的空方块('E')被挖出,修改它为数字('1'到'8'),表示相邻地雷的数量。
4. 如果在此次点击中,若无更多方块可被揭露,则返回面板。
注意:
- 输入矩阵的宽和高的范围为 [1,50]。
- 点击的位置只能是未被挖出的方块 ('M' 或者 'E'),这也意味着面板至少包含一个可点击的方块。
- 输入面板不会是游戏结束的状态(即有地雷已被挖出)。
- 简单起见,未提及的规则在这个问题中可被忽略。例如,当游戏结束时你不需要挖出所有地雷,考虑所有你可能赢得游戏或标记方块的情况。
## 解题思路
- 给出一张扫雷地图和点击的坐标,M 代表雷,E 代表还没有点击过的空砖块,B 代表点击过的空砖块,1-8 代表砖块周围 8 个方块里面有雷的个数,X 代表点到了雷。问点击一次以后,输出更新点击以后的地图。
- DPS 和 BFS 都可以解题。先根据原图预处理地图,记录出最终地图的状态,0 代表空白砖块,1-8 代表雷的个数,-1 代表是雷。再 DFS 遍历这张处理后的图,输出最终的地图即可。
## 代码
```go
func updateBoard(board [][]byte, click []int) [][]byte {
if board[click[0]][click[1]] == 'M' {
board[click[0]][click[1]] = 'X'
return board
}
mineMap := make([][]int, len(board))
for i := range board {
mineMap[i] = make([]int, len(board[i]))
}
for i := range board {
for j := range board[i] {
if board[i][j] == 'M' {
mineMap[i][j] = -1
for _, d := range dir8 {
nx, ny := i+d[0], j+d[1]
if isInBoard(board, nx, ny) && mineMap[nx][ny] >= 0 {
mineMap[nx][ny]++
}
}
}
}
}
mineSweeper(click[0], click[1], board, mineMap, dir8)
return board
}
func mineSweeper(x, y int, board [][]byte, mineMap [][]int, dir8 [][]int) {
if board[x][y] != 'M' && board[x][y] != 'E' {
return
}
if mineMap[x][y] == -1 {
board[x][y] = 'X'
} else if mineMap[x][y] > 0 {
board[x][y] = '0' + byte(mineMap[x][y])
} else {
board[x][y] = 'B'
for _, d := range dir8 {
nx, ny := x+d[0], y+d[1]
if isInBoard(board, nx, ny) && mineMap[nx][ny] >= 0 {
mineSweeper(nx, ny, board, mineMap, dir8)
}
}
}
}
```

View File

@@ -0,0 +1,37 @@
package leetcode
func shoppingOffers(price []int, special [][]int, needs []int) int {
res := -1
dfsShoppingOffers(price, special, needs, 0, &res)
return res
}
func dfsShoppingOffers(price []int, special [][]int, needs []int, pay int, res *int) {
noNeeds := true
// 剪枝
for _, need := range needs {
if need < 0 {
return
}
if need != 0 {
noNeeds = false
}
}
if len(special) == 0 || noNeeds {
for i, p := range price {
pay += (p * needs[i])
}
if pay < *res || *res == -1 {
*res = pay
}
return
}
newNeeds := make([]int, len(needs))
copy(newNeeds, needs)
for i, n := range newNeeds {
newNeeds[i] = n - special[0][i]
}
dfsShoppingOffers(price, special, newNeeds, pay+special[0][len(price)], res)
dfsShoppingOffers(price, special[1:], newNeeds, pay+special[0][len(price)], res)
dfsShoppingOffers(price, special[1:], needs, pay, res)
}

View File

@@ -0,0 +1,49 @@
package leetcode
import (
"fmt"
"testing"
)
type question638 struct {
para638
ans638
}
// para 是参数
// one 代表第一个参数
type para638 struct {
price []int
special [][]int
needs []int
}
// ans 是答案
// one 代表第一个答案
type ans638 struct {
one int
}
func Test_Problem638(t *testing.T) {
qs := []question638{
question638{
para638{[]int{2, 5}, [][]int{[]int{3, 0, 5}, []int{1, 2, 10}}, []int{3, 2}},
ans638{14},
},
question638{
para638{[]int{2, 3, 4}, [][]int{[]int{1, 1, 0, 4}, []int{2, 2, 1, 9}}, []int{1, 2, 1}},
ans638{11},
},
}
fmt.Printf("------------------------Leetcode Problem 638------------------------\n")
for _, q := range qs {
_, p := q.ans638, q.para638
fmt.Printf("【input】:%v 【output】:%v\n", p, shoppingOffers(p.price, p.special, p.needs))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,128 @@
# 638. Shopping Offers
## 题目
In LeetCode Store, there are some kinds of items to sell. Each item has a price.
However, there are some special offers, and a special offer consists of one or more different kinds of items with a sale price.
You are given the each item's price, a set of special offers, and the number we need to buy for each item. The job is to output the lowest price you have to pay for **exactly** certain items as given, where you could make optimal use of the special offers.
Each special offer is represented in the form of an array, the last number represents the price you need to pay for this special offer, other numbers represents how many specific items you could get if you buy this offer.
You could use any of special offers as many times as you want.
**Example 1**:
```
Input: [2,5], [[3,0,5],[1,2,10]], [3,2]
Output: 14
Explanation:
There are two kinds of items, A and B. Their prices are $2 and $5 respectively.
In special offer 1, you can pay $5 for 3A and 0B
In special offer 2, you can pay $10 for 1A and 2B.
You need to buy 3A and 2B, so you may pay $10 for 1A and 2B (special offer #2), and $4 for 2A.
```
**Example 2**:
```
Input: [2,3,4], [[1,1,0,4],[2,2,1,9]], [1,2,1]
Output: 11
Explanation:
The price of A is $2, and $3 for B, $4 for C.
You may pay $4 for 1A and 1B, and $9 for 2A ,2B and 1C.
You need to buy 1A ,2B and 1C, so you may pay $4 for 1A and 1B (special offer #1), and $3 for 1B, $4 for 1C.
You cannot add more items, though only $9 for 2A ,2B and 1C.
```
**Note**:
1. There are at most 6 kinds of items, 100 special offers.
2. For each item, you need to buy at most 6 of them.
3. You are **not** allowed to buy more items than you want, even if that would lower the overall price.
## 题目大意
在 LeetCode 商店中, 有许多在售的物品。然而,也有一些大礼包,每个大礼包以优惠的价格捆绑销售一组物品。
现给定每个物品的价格,每个大礼包包含物品的清单,以及待购物品清单。请输出确切完成待购清单的最低花费。每个大礼包的由一个数组中的一组数据描述,最后一个数字代表大礼包的价格,其他数字分别表示内含的其他种类物品的数量。任意大礼包可无限次购买。
例子 1:
```
输入: [2,5], [[3,0,5],[1,2,10]], [3,2]
输出: 14
解释:
有A和B两种物品,价格分别为¥2和¥5。
大礼包1,你可以以¥5的价格购买3A和0B。
大礼包2, 你可以以¥10的价格购买1A和2B。
你需要购买3个A和2个B, 所以你付了¥10购买了1A和2B(大礼包2),以及¥4购买2A。
```
例子 2:
```
输入: [2,3,4], [[1,1,0,4],[2,2,1,9]], [1,2,1]
输出: 11
解释:
A,B,C的价格分别为¥2,¥3,¥4.
你可以用¥4购买1A和1B,也可以用¥9购买2A,2B和1C。
你需要买1A,2B和1C,所以你付了¥4买了1A和1B(大礼包1),以及¥3购买1B, ¥4购买1C。
你不可以购买超出待购清单的物品,尽管购买大礼包2更加便宜。
```
说明:
- 最多6种物品, 100种大礼包。
- 每种物品,你最多只需要购买6个。
- 你不可以购买超出待购清单的物品,即使更便宜。
## 解题思路
- 给出 3 个数组,3 个数组分别代表的意义是在售的商品价格,多个礼包以及礼包内每个商品的数量和总价,购物清单上需要购买每个商品的数量。问购买清单上的所有商品所需的最低花费。
- 这一题可以用 DFS 暴力解题,也可以用 DP。笔者这题先用 DFS 来解答。设当前搜索到的状态为 `shopping(price, special, needs)`,其中 `price` 和 `special` 为题目中所述的物品的单价和捆绑销售的大礼包,而 `needs` 为当前需要的每种物品的数量。针对于每个商品,可以有 3 种购买规则,第一种,选礼包里面的第一个优惠购买,第二种,不选当前礼包优惠,选下一个优惠进行购买,第三种,不使用优惠,直接购买。这样就对应了 3 种 DFS 的方向。具体见代码。如果选择了礼包优惠,那么递归到下一层,`need` 需要对应减少礼包里面的数量,最终金额累加。当所有情况遍历完以后,可以返回出最小花费。
- 这一题需要注意的剪枝情况:是否需要购买礼包。题目中要求了,不能购买超过清单上数量的商品,即使价格便宜,也不行。例如可以买 n 个礼包 A,但是最终商品数量超过了清单上的商品,这种购买方式是不行的。所以需要先判断当前递归中,满足 `need` 和 `price` 条件的,能否使用礼包。这里包含 2 种情况,一种是当前商品已经满足清单个数了,不需要再买了;还有一种情况是已经超过清单数量了,那这种情况需要立即返回,当前这种购买方式不合题意。
## 代码
```go
func shoppingOffers(price []int, special [][]int, needs []int) int {
res := -1
dfsShoppingOffers(price, special, needs, 0, &res)
return res
}
func dfsShoppingOffers(price []int, special [][]int, needs []int, pay int, res *int) {
noNeeds := true
// 剪枝
for _, need := range needs {
if need < 0 {
return
}
if need != 0 {
noNeeds = false
}
}
if len(special) == 0 || noNeeds {
for i, p := range price {
pay += (p * needs[i])
}
if pay < *res || *res == -1 {
*res = pay
}
return
}
newNeeds := make([]int, len(needs))
copy(newNeeds, needs)
for i, n := range newNeeds {
newNeeds[i] = n - special[0][i]
}
dfsShoppingOffers(price, special, newNeeds, pay+special[0][len(price)], res)
dfsShoppingOffers(price, special[1:], newNeeds, pay+special[0][len(price)], res)
dfsShoppingOffers(price, special[1:], needs, pay, res)
}
```

View File

@@ -0,0 +1,42 @@
package leetcode
var dir = [][]int{
[]int{-1, 0},
[]int{0, 1},
[]int{1, 0},
[]int{0, -1},
}
func maxAreaOfIsland(grid [][]int) int {
res := 0
for i, row := range grid {
for j, col := range row {
if col == 0 {
continue
}
area := areaOfIsland(grid, i, j)
if area > res {
res = area
}
}
}
return res
}
func isInGrid(grid [][]int, x, y int) bool {
return x >= 0 && x < len(grid) && y >= 0 && y < len(grid[0])
}
func areaOfIsland(grid [][]int, x, y int) int {
if !isInGrid(grid, x, y) || grid[x][y] == 0 {
return 0
}
grid[x][y] = 0
total := 1
for i := 0; i < 4; i++ {
nx := x + dir[i][0]
ny := y + dir[i][1]
total += areaOfIsland(grid, nx, ny)
}
return total
}

View File

@@ -0,0 +1,90 @@
package leetcode
import (
"fmt"
"testing"
)
type question695 struct {
para695
ans695
}
// para 是参数
// one 代表第一个参数
type para695 struct {
one [][]int
}
// ans 是答案
// one 代表第一个答案
type ans695 struct {
one int
}
func Test_Problem695(t *testing.T) {
qs := []question695{
question695{
para695{[][]int{
[]int{1, 1, 1, 1, 0},
[]int{1, 1, 0, 1, 0},
[]int{1, 1, 0, 0, 0},
[]int{0, 0, 0, 0, 0},
}},
ans695{9},
},
question695{
para695{[][]int{
[]int{1, 1, 0, 0, 0},
[]int{1, 1, 0, 0, 0},
[]int{0, 0, 1, 0, 0},
[]int{0, 0, 0, 1, 1},
}},
ans695{4},
},
question695{
para695{[][]int{
[]int{1, 1, 1, 1, 1, 1, 1, 0},
[]int{1, 0, 0, 0, 0, 1, 1, 0},
[]int{1, 0, 1, 0, 1, 1, 1, 0},
[]int{1, 0, 0, 0, 0, 1, 0, 1},
[]int{1, 1, 1, 1, 1, 1, 1, 0},
}},
ans695{23},
},
question695{
para695{[][]int{
[]int{0, 0, 1, 0, 0},
[]int{0, 1, 0, 1, 0},
[]int{0, 1, 1, 1, 0},
}},
ans695{5},
},
question695{
para695{[][]int{
[]int{1, 1, 1, 1, 1, 1, 1},
[]int{1, 0, 0, 0, 0, 0, 1},
[]int{1, 0, 1, 1, 1, 0, 1},
[]int{1, 0, 1, 0, 1, 0, 1},
[]int{1, 0, 1, 1, 1, 0, 1},
[]int{1, 0, 0, 0, 0, 0, 1},
[]int{1, 1, 1, 1, 1, 1, 1},
}},
ans695{24},
},
}
fmt.Printf("------------------------Leetcode Problem 695------------------------\n")
for _, q := range qs {
_, p := q.ans695, q.para695
fmt.Printf("【input】:%v 【output】:%v\n", p, maxAreaOfIsland(p.one))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,76 @@
# 695. Max Area of Island
## 题目
Given a non-empty 2D array `grid` of 0's and 1's, an **island** is a group of `1`'s (representing land) connected 4-directionally (horizontal or vertical.) You may assume all four edges of the grid are surrounded by water.
Find the maximum area of an island in the given 2D array. (If there is no island, the maximum area is 0.)
**Example 1**:
```
[[0,0,1,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,1,1,0,1,0,0,0,0,0,0,0,0],
[0,1,0,0,1,1,0,0,1,0,1,0,0],
[0,1,0,0,1,1,0,0,1,1,1,0,0],
[0,0,0,0,0,0,0,0,0,0,1,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,0,0,0,0,0,0,1,1,0,0,0,0]]
```
Given the above grid, return`6`. Note the answer is not 11, because the island must be connected 4-directionally.
**Example 2**:
```
[[0,0,0,0,0,0,0,0]]
```
Given the above grid, return`0`.
**Note**: The length of each dimension in the given `grid` does not exceed 50.
## 题目大意
给定一个包含了一些 0 和 1 的非空二维数组 grid 。一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为 0 。)
## 解题思路
- 给出一个地图,要求计算上面岛屿的面积。注意岛屿的定义是四周都是海(为 0 的点),如果土地(为 1 的点)靠在地图边缘,不能算是岛屿。
- 这一题和第 200 题,第 1254 题解题思路是一致的。DPS 深搜。这不过这一题需要多处理 2 件事情,一个是注意靠边缘的岛屿不能计算在内,二是动态维护岛屿的最大面积。
## 代码
```go
func maxAreaOfIsland(grid [][]int) int {
res := 0
for i, row := range grid {
for j, col := range row {
if col == 0 {
continue
}
area := areaOfIsland(grid, i, j)
if area > res {
res = area
}
}
}
return res
}
func areaOfIsland(grid [][]int, x, y int) int {
if !isInGrid(grid, x, y) || grid[x][y] == 0 {
return 0
}
grid[x][y] = 0
total := 1
for i := 0; i < 4; i++ {
nx := x + dir[i][0]
ny := y + dir[i][1]
total += areaOfIsland(grid, nx, ny)
}
return total
}
```

View File

@@ -0,0 +1,39 @@
package leetcode
import "math"
const number = "0123456789"
func crackSafe(n int, k int) string {
if n == 1 {
return number[:k]
}
visit, total := map[string]bool{}, int(math.Pow(float64(k), float64(n)))
str := make([]byte, 0, total+n-1)
for i := 1; i != n; i++ {
str = append(str, '0')
}
dfsCrackSafe(total, n, k, &str, &visit)
return string(str)
}
func dfsCrackSafe(depth, n, k int, str *[]byte, visit *map[string]bool) bool {
if depth == 0 {
return true
}
for i := 0; i != k; i++ {
*str = append(*str, byte('0'+i))
cur := string((*str)[len(*str)-n:])
if _, ok := (*visit)[cur]; ok != true {
(*visit)[cur] = true
if dfsCrackSafe(depth-1, n, k, str, visit) {
// 只有这里不需要删除
return true
}
delete(*visit, cur)
}
// 删除
*str = (*str)[0 : len(*str)-1]
}
return false
}

View File

@@ -0,0 +1,48 @@
package leetcode
import (
"fmt"
"testing"
)
type question753 struct {
para753
ans753
}
// para 是参数
// one 代表第一个参数
type para753 struct {
n int
k int
}
// ans 是答案
// one 代表第一个答案
type ans753 struct {
one string
}
func Test_Problem753(t *testing.T) {
qs := []question753{
question753{
para753{1, 2},
ans753{"01"},
},
question753{
para753{2, 2},
ans753{"00110"},
},
}
fmt.Printf("------------------------Leetcode Problem 753------------------------\n")
for _, q := range qs {
_, p := q.ans753, q.para753
fmt.Printf("【input】:%v 【output】:%v\n", p, crackSafe(p.n, p.k))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,91 @@
# 753. Cracking the Safe
## 题目
There is a box protected by a password. The password is a sequence of `n` digits where each digit can be one of the first `k` digits `0, 1, ..., k-1`.
While entering a password, the last `n` digits entered will automatically be matched against the correct password.
For example, assuming the correct password is `"345"`, if you type `"012345"`, the box will open because the correct password matches the suffix of the entered password.
Return any password of **minimum length** that is guaranteed to open the box at some point of entering it.
**Example 1**:
```
Input: n = 1, k = 2
Output: "01"
Note: "10" will be accepted too.
```
**Example 2**:
```
Input: n = 2, k = 2
Output: "00110"
Note: "01100", "10011", "11001" will be accepted too.
```
**Note**:
1. `n` will be in the range `[1, 4]`.
2. `k` will be in the range `[1, 10]`.
3. `k^n` will be at most `4096`.
## 题目大意
有一个需要密码才能打开的保险箱。密码是 n 位数, 密码的每一位是 k 位序列 0, 1, ..., k-1 中的一个 。你可以随意输入密码,保险箱会自动记住最后 n 位输入,如果匹配,则能够打开保险箱。举个例子,假设密码是 "345",你可以输入 "012345" 来打开它,只是你输入了 6 个字符.请返回一个能打开保险箱的最短字符串。
提示:
- n 的范围是 [1, 4]。
- k 的范围是 [1, 10]。
- k^n 最大可能为 4096。
## 解题思路
- 给出 2 个数字 n 和 k,n 代表密码是 n 位数,k 代表密码是 k 位。保险箱会记住最后 n 位输入。返回一个能打开保险箱的最短字符串。
- 看到题目中的数据范围,数据范围很小,所以可以考虑用 DFS。想解开保险箱,当然是暴力破解,枚举所有可能。题目要求我们输出一个最短的字符串,这里是本题的关键,为何有最短呢?这里有贪心的思想。如果下一次递归可以利用上一次的 n-1 位,那么最终输出的字符串肯定是最短的。(笔者这里就不证明了),例如,例子 2 中,最短的字符串是 00,01,11,10。每次尝试都利用前一次的 n-1 位。想通了这个问题,利用 DFS 暴力回溯即可。
## 代码
```go
const number = "0123456789"
func crackSafe(n int, k int) string {
if n == 1 {
return number[:k]
}
visit, total := map[string]bool{}, int(math.Pow(float64(k), float64(n)))
str := make([]byte, 0, total+n-1)
for i := 1; i != n; i++ {
str = append(str, '0')
}
dfsCrackSafe(total, n, k, &str, &visit)
return string(str)
}
func dfsCrackSafe(depth, n, k int, str *[]byte, visit *map[string]bool) bool {
if depth == 0 {
return true
}
for i := 0; i != k; i++ {
*str = append(*str, byte('0'+i))
cur := string((*str)[len(*str)-n:])
if _, ok := (*visit)[cur]; ok != true {
(*visit)[cur] = true
if dfsCrackSafe(depth-1, n, k, str, visit) {
// 只有这里不需要删除
return true
}
delete(*visit, cur)
}
// 删除
*str = (*str)[0 : len(*str)-1]
}
return false
}
```

View File

@@ -0,0 +1,26 @@
package leetcode
func eventualSafeNodes(graph [][]int) []int {
res, color := []int{}, make([]int, len(graph))
for i := range graph {
if dfsEventualSafeNodes(graph, i, color) {
res = append(res, i)
}
}
return res
}
// colors: WHITE 0, GRAY 1, BLACK 2;
func dfsEventualSafeNodes(graph [][]int, idx int, color []int) bool {
if color[idx] > 0 {
return color[idx] == 2
}
color[idx] = 1
for i := range graph[idx] {
if !dfsEventualSafeNodes(graph, graph[idx][i], color) {
return false
}
}
color[idx] = 2
return true
}

View File

@@ -0,0 +1,42 @@
package leetcode
import (
"fmt"
"testing"
)
type question802 struct {
para802
ans802
}
// para 是参数
// one 代表第一个参数
type para802 struct {
graph [][]int
}
// ans 是答案
// one 代表第一个答案
type ans802 struct {
one []int
}
func Test_Problem802(t *testing.T) {
qs := []question802{
question802{
para802{[][]int{[]int{1, 2}, []int{2, 3}, []int{5}, []int{0}, []int{5}, []int{}, []int{}}},
ans802{[]int{2, 4, 5, 6}},
},
}
fmt.Printf("------------------------Leetcode Problem 802------------------------\n")
for _, q := range qs {
_, p := q.ans802, q.para802
fmt.Printf("【input】:%v 【output】:%v\n", p, eventualSafeNodes(p.graph))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,72 @@
# 802. Find Eventual Safe States
## 题目
In a directed graph, we start at some node and every turn, walk along a directed edge of the graph. If we reach a node that is terminal (that is, it has no outgoing directed edges), we stop.
Now, say our starting node is *eventually safe* if and only if we must eventually walk to a terminal node. More specifically, there exists a natural number `K` so that for any choice of where to walk, we must have stopped at a terminal node in less than `K` steps.
Which nodes are eventually safe? Return them as an array in sorted order.
The directed graph has `N` nodes with labels `0, 1, ..., N-1`, where `N` is the length of `graph`. The graph is given in the following form: `graph[i]` is a list of labels `j` such that `(i, j)` is a directed edge of the graph.
```
Example:
Input: graph = [[1,2],[2,3],[5],[0],[5],[],[]]
Output: [2,4,5,6]
Here is a diagram of the above graph.
```
![https://s3-lc-upload.s3.amazonaws.com/uploads/2018/03/17/picture1.png](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/03/17/picture1.png)
**Note**:
- `graph` will have length at most `10000`.
- The number of edges in the graph will not exceed `32000`.
- Each `graph[i]` will be a sorted list of different integers, chosen within the range `[0, graph.length - 1]`.
## 题目大意
在有向图中, 我们从某个节点和每个转向处开始, 沿着图的有向边走。 如果我们到达的节点是终点 (即它没有连出的有向边), 我们停止。现在, 如果我们最后能走到终点,那么我们的起始节点是最终安全的。 更具体地说, 存在一个自然数 K,  无论选择从哪里开始行走, 我们走了不到 K 步后必能停止在一个终点。哪些节点最终是安全的? 结果返回一个有序的数组。
提示:
- graph 节点数不超过 10000.
- 图的边数不会超过 32000.
- 每个 graph[i] 被排序为不同的整数列表, 在区间 [0, graph.length - 1] 中选取。
## 解题思路
- 给出一个有向图,要求找出所有“安全”节点。“安全”节点的定义是:存在一个自然数 K, 无论选择从哪里开始行走, 我们走了不到 K 步后必能停止在一个终点。
- 这一题可以用拓扑排序,也可以用 DFS 染色来解答。这里用 DFS 来解答。对于每个节点,我们有 3 种染色的方法:白色 0 号节点表示该节点还没有被访问过;灰色 1 号节点表示该节点在栈中(这一轮搜索中被访问过)或者在环中;黑色 2 号节点表示该节点的所有相连的节点都被访问过,且该节点不在环中。当我们第一次访问一个节点时,我们把它从白色变成灰色,并继续搜索与它相连的节点。如果在搜索过程中我们遇到一个灰色的节点,那么说明找到了一个环,此时退出搜索,所有的灰色节点保持不变(即从任意一个灰色节点开始,都能走到环中),如果搜索过程中,我们没有遇到灰色的节点,那么在回溯到当前节点时,我们把它从灰色变成黑色,即表示它是一个安全的节点。
## 代码
```go
func eventualSafeNodes(graph [][]int) []int {
res, color := []int{}, make([]int, len(graph))
for i := range graph {
if dfsEventualSafeNodes(graph, i, color) {
res = append(res, i)
}
}
return res
}
// colors: WHITE 0, GRAY 1, BLACK 2;
func dfsEventualSafeNodes(graph [][]int, idx int, color []int) bool {
if color[idx] > 0 {
return color[idx] == 2
}
color[idx] = 1
for i := range graph[idx] {
if !dfsEventualSafeNodes(graph, graph[idx][i], color) {
return false
}
}
color[idx] = 2
return true
}
```

View File

@@ -0,0 +1,18 @@
package leetcode
func canVisitAllRooms(rooms [][]int) bool {
visited := make(map[int]bool)
visited[0] = true
dfsVisitAllRooms(rooms, visited, 0)
return len(rooms) == len(visited)
}
func dfsVisitAllRooms(es [][]int, visited map[int]bool, from int) {
for _, to := range es[from] {
if visited[to] {
continue
}
visited[to] = true
dfsVisitAllRooms(es, visited, to)
}
}

View File

@@ -0,0 +1,47 @@
package leetcode
import (
"fmt"
"testing"
)
type question841 struct {
para841
ans841
}
// para 是参数
// one 代表第一个参数
type para841 struct {
rooms [][]int
}
// ans 是答案
// one 代表第一个答案
type ans841 struct {
one bool
}
func Test_Problem841(t *testing.T) {
qs := []question841{
question841{
para841{[][]int{[]int{1}, []int{2}, []int{3}, []int{}}},
ans841{true},
},
question841{
para841{[][]int{[]int{1, 3}, []int{3, 0, 1}, []int{2}, []int{0}}},
ans841{false},
},
}
fmt.Printf("------------------------Leetcode Problem 841------------------------\n")
for _, q := range qs {
_, p := q.ans841, q.para841
fmt.Printf("【input】:%v 【output】:%v\n", p, canVisitAllRooms(p.rooms))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,79 @@
# 841. Keys and Rooms
## 题目
There are `N` rooms and you start in room `0`. Each room has a distinct number in `0, 1, 2, ..., N-1`, and each room may have some keys to access the next room.
Formally, each room `i` has a list of keys `rooms[i]`, and each key `rooms[i][j]` is an integer in `[0, 1, ..., N-1]` where `N = rooms.length`. A key `rooms[i][j] = v` opens the room with number `v`.
Initially, all the rooms start locked (except for room `0`).
You can walk back and forth between rooms freely.
Return `true` if and only if you can enter every room.
**Example 1**:
```
Input: [[1],[2],[3],[]]
Output: true
Explanation:
We start in room 0, and pick up key 1.
We then go to room 1, and pick up key 2.
We then go to room 2, and pick up key 3.
We then go to room 3. Since we were able to go to every room, we return true.
```
**Example 2**:
```
Input: [[1,3],[3,0,1],[2],[0]]
Output: false
Explanation: We can't enter the room with number 2.
```
**Note**:
1. `1 <= rooms.length <= 1000`
2. `0 <= rooms[i].length <= 1000`
3. The number of keys in all rooms combined is at most `3000`.
## 题目大意
有 N 个房间,开始时你位于 0 号房间。每个房间有不同的号码:0,1,2,...,N-1,并且房间里可能有一些钥匙能使你进入下一个房间。
在形式上,对于每个房间 i 都有一个钥匙列表 rooms[i],每个钥匙 rooms[i][j] 由 [0,1,...,N-1] 中的一个整数表示,其中 N = rooms.length。 钥匙 rooms[i][j] = v 可以打开编号为 v 的房间。最初,除 0 号房间外的其余所有房间都被锁住。你可以自由地在房间之间来回走动。如果能进入每个房间返回 true,否则返回 false。
提示:
- 1 <= rooms.length <= 1000
- 0 <= rooms[i].length <= 1000
- 所有房间中的钥匙数量总计不超过 3000。
## 解题思路
- 给出一个房间数组,每个房间里面装了一些钥匙。0 号房间默认是可以进入的,房间进入顺序没有要求,问最终能否进入所有房间。
- 用 DFS 依次深搜所有房间的钥匙,如果都能访问到,最终输出 true。这题算是 DFS 里面的简单题。
## 代码
```go
func canVisitAllRooms(rooms [][]int) bool {
visited := make(map[int]bool)
visited[0] = true
dfsVisitAllRooms(rooms, visited, 0)
return len(rooms) == len(visited)
}
func dfsVisitAllRooms(es [][]int, visited map[int]bool, from int) {
for _, to := range es[from] {
if visited[to] {
continue
}
visited[to] = true
dfsVisitAllRooms(es, visited, to)
}
}
```

View File

@@ -0,0 +1,40 @@
package leetcode
func loudAndRich(richer [][]int, quiet []int) []int {
edges := make([][]int, len(quiet))
for i := range edges {
edges[i] = []int{}
}
indegrees := make([]int, len(quiet))
for _, edge := range richer {
n1, n2 := edge[0], edge[1]
edges[n1] = append(edges[n1], n2)
indegrees[n2]++
}
res := make([]int, len(quiet))
for i := range res {
res[i] = i
}
queue := []int{}
for i, v := range indegrees {
if v == 0 {
queue = append(queue, i)
}
}
for len(queue) > 0 {
nexts := []int{}
for _, n1 := range queue {
for _, n2 := range edges[n1] {
indegrees[n2]--
if quiet[res[n2]] > quiet[res[n1]] {
res[n2] = res[n1]
}
if indegrees[n2] == 0 {
nexts = append(nexts, n2)
}
}
}
queue = nexts
}
return res
}

View File

@@ -0,0 +1,43 @@
package leetcode
import (
"fmt"
"testing"
)
type question851 struct {
para851
ans851
}
// para 是参数
// one 代表第一个参数
type para851 struct {
richer [][]int
quiet []int
}
// ans 是答案
// one 代表第一个答案
type ans851 struct {
one []int
}
func Test_Problem851(t *testing.T) {
qs := []question851{
question851{
para851{[][]int{[]int{1, 0}, []int{2, 1}, []int{3, 1}, []int{3, 7}, []int{4, 3}, []int{5, 3}}, []int{3, 2, 5, 4, 6, 1, 7, 0}},
ans851{[]int{5, 5, 2, 5, 4, 5, 6, 7}},
},
}
fmt.Printf("------------------------Leetcode Problem 851------------------------\n")
for _, q := range qs {
_, p := q.ans851, q.para851
fmt.Printf("【input】:%v 【output】:%v\n", p, loudAndRich(p.richer, p.quiet))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,107 @@
# 851. Loud and Rich
## 题目
In a group of N people (labelled `0, 1, 2, ..., N-1`), each person has different amounts of money, and different levels of quietness.
For convenience, we'll call the person with label `x`, simply "person `x`".
We'll say that `richer[i] = [x, y]` if person `x` definitely has more money than person `y`. Note that `richer` may only be a subset of valid observations.
Also, we'll say `quiet = q` if person x has quietness `q`.
Now, return `answer`, where `answer = y` if `y` is the least quiet person (that is, the person `y` with the smallest value of `quiet[y]`), among all people who definitely have equal to or more money than person `x`.
**Example 1**:
```
Input: richer = [[1,0],[2,1],[3,1],[3,7],[4,3],[5,3],[6,3]], quiet = [3,2,5,4,6,1,7,0]
Output: [5,5,2,5,4,5,6,7]
Explanation:
answer[0] = 5.
Person 5 has more money than 3, which has more money than 1, which has more money than 0.
The only person who is quieter (has lower quiet[x]) is person 7, but
it isn't clear if they have more money than person 0.
answer[7] = 7.
Among all people that definitely have equal to or more money than person 7
(which could be persons 3, 4, 5, 6, or 7), the person who is the quietest (has lower quiet[x])
is person 7.
The other answers can be filled out with similar reasoning.
```
**Note**:
1. `1 <= quiet.length = N <= 500`
2. `0 <= quiet[i] < N`, all `quiet[i]` are different.
3. `0 <= richer.length <= N * (N-1) / 2`
4. `0 <= richer[i][j] < N`
5. `richer[i][0] != richer[i][1]`
6. `richer[i]`'s are all different.
7. The observations in `richer` are all logically consistent.
## 题目大意
在一组 N 个人(编号为 0, 1, 2, ..., N-1)中,每个人都有不同数目的钱,以及不同程度的安静(quietness)。为了方便起见,我们将编号为 x 的人简称为 "person x "。如果能够肯定 person x 比 person y 更有钱的话,我们会说 richer[i] = [x, y] 。注意 richer 可能只是有效观察的一个子集。另外,如果 person x 的安静程度为 q ,我们会说 quiet[x] = q 。现在,返回答案 answer ,其中 answer[x] = y 的前提是,在所有拥有的钱不少于 person x 的人中,person y 是最安静的人(也就是安静值 quiet[y] 最小的人)。
提示:
- 1 <= quiet.length = N <= 500
- 0 <= quiet[i] < N,所有 quiet[i] 都不相同。
- 0 <= richer.length <= N * (N-1) / 2
- 0 <= richer[i][j] < N
- richer[i][0] != richer[i][1]
- richer[i] 都是不同的。
- 对 richer 的观察在逻辑上是一致的。
## 解题思路
- 给出 2 个数组,richer 和 quiet,要求输出 answer,其中 answer = y 的前提是,在所有拥有的钱不少于 x 的人中,y 是最安静的人(也就是安静值 quiet[y] 最小的人)
- 由题意可知,`richer` 构成了一个有向无环图,首先使用字典建立图的关系,找到比当前下标编号富有的所有的人。然后使用广度优先层次遍历,不断的使用富有的人,但是安静值更小的人更新子节点即可。
- 这一题还可以用拓扑排序来解答。将 `richer` 中描述的关系看做边,如果 `x > y`,则 `x` 指向 `y`。将 `quiet` 看成权值。用一个数组记录答案,初始时 `ans[i] = i`。然后对原图做拓扑排序,对于每一条边,如果发现 `quiet[ans[v]] > quiet[ans[u]]`,则 `ans[v]` 的答案为 `ans[u]`。时间复杂度即为拓扑排序的时间复杂度为 `O(m+n)`。空间复杂度需要 `O(m)` 的数组建图,需要 `O(n)` 的数组记录入度以及存储队列,所以空间复杂度为 `O(m+n)`。
## 代码
```go
func loudAndRich(richer [][]int, quiet []int) []int {
edges := make([][]int, len(quiet))
for i := range edges {
edges[i] = []int{}
}
indegrees := make([]int, len(quiet))
for _, edge := range richer {
n1, n2 := edge[0], edge[1]
edges[n1] = append(edges[n1], n2)
indegrees[n2]++
}
res := make([]int, len(quiet))
for i := range res {
res[i] = i
}
queue := []int{}
for i, v := range indegrees {
if v == 0 {
queue = append(queue, i)
}
}
for len(queue) > 0 {
nexts := []int{}
for _, n1 := range queue {
for _, n2 := range edges[n1] {
indegrees[n2]--
if quiet[res[n2]] > quiet[res[n1]] {
res[n2] = res[n1]
}
if indegrees[n2] == 0 {
nexts = append(nexts, n2)
}
}
}
queue = nexts
}
return res
}
```

View File

@@ -0,0 +1,30 @@
package leetcode
func shortestSubarray(A []int, K int) int {
res, prefixSum := len(A)+1, make([]int, len(A)+1)
for i := 0; i < len(A); i++ {
prefixSum[i+1] = prefixSum[i] + A[i]
}
// deque 中保存递增的 prefixSum 下标
deque := []int{}
for i := range prefixSum {
// 下面这个循环希望能找到 [deque[0], i] 区间内累加和 >= K,如果找到了就更新答案
for len(deque) > 0 && prefixSum[i]-prefixSum[deque[0]] >= K {
length := i - deque[0]
if res > length {
res = length
}
// 找到第一个 deque[0] 能满足条件以后,就移除它,因为它是最短长度的子序列了
deque = deque[1:]
}
// 下面这个循环希望能保证 prefixSum[deque[i]] 递增
for len(deque) > 0 && prefixSum[i] <= prefixSum[deque[len(deque)-1]] {
deque = deque[:len(deque)-1]
}
deque = append(deque, i)
}
if res <= len(A) {
return res
}
return -1
}

View File

@@ -0,0 +1,52 @@
package leetcode
import (
"fmt"
"testing"
)
type question862 struct {
para862
ans862
}
// para 是参数
// one 代表第一个参数
type para862 struct {
A []int
K int
}
// ans 是答案
// one 代表第一个答案
type ans862 struct {
one int
}
func Test_Problem862(t *testing.T) {
qs := []question862{
question862{
para862{[]int{1}, 1},
ans862{1},
},
question862{
para862{[]int{1, 2}, 4},
ans862{-1},
},
question862{
para862{[]int{2, -1, 2}, 3},
ans862{3},
},
}
fmt.Printf("------------------------Leetcode Problem 862------------------------\n")
for _, q := range qs {
_, p := q.ans862, q.para862
fmt.Printf("【input】:%v 【output】:%v\n", p, shortestSubarray(p.A, p.K))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,89 @@
# 862. Shortest Subarray with Sum at Least K
## 题目
Return the **length** of the shortest, non-empty, contiguous subarray of `A` with sum at least `K`.
If there is no non-empty subarray with sum at least `K`, return `-1`.
**Example 1**:
```
Input: A = [1], K = 1
Output: 1
```
**Example 2**:
```
Input: A = [1,2], K = 4
Output: -1
```
**Example 3**:
```
Input: A = [2,-1,2], K = 3
Output: 3
```
**Note**:
1. `1 <= A.length <= 50000`
2. `-10 ^ 5 <= A[i] <= 10 ^ 5`
3. `1 <= K <= 10 ^ 9`
## 题目大意
返回 A 的最短的非空连续子数组的长度,该子数组的和至少为 K 。如果没有和至少为 K 的非空子数组,返回 -1 。
提示:
- 1 <= A.length <= 50000
- -10 ^ 5 <= A[i] <= 10 ^ 5
- 1 <= K <= 10 ^ 9
## 解题思路
- 给出一个数组,要求找出一个最短的,非空的,连续的子序列且累加和至少为 k 。
- 由于给的数组里面可能存在负数,所以子数组的累加和不会随着数组的长度增加而增加。题目中要求区间和,理所应当需要利用 `prefixSum` 前缀和,先计算出 `prefixSum` 前缀和。
- 简化一下题目的要求,即能否找到 `prefixSum[y] - prefixSum[x] ≥ K` ,且 `y - x` 的差值最小。如果固定的 `y`,那么对于 `x`,`x` 越大,`y - x` 的差值就越小(因为 `x` 越逼近 `y`)。所以想求区间 `[x, y]` 的最短距离,需要保证 `y` 尽量小,`x` 尽量大,这样 `[x, y]` 区间距离最小。那么有以下 2 点“常识”一定成立:
1. 如果 `x1 < x2` ,并且 `prefixSum[x2] ≤ prefixSum[x1]`,说明结果一定不会取 `x1`。因为如果 `prefixSum[x1] ≤ prefixSum[y] - k`,那么 `prefixSum[x2] ≤ prefixSum[x1] ≤ prefixSum[y] - k`,`x2` 也能满足题意,并且 `x2` 比 `x1` 更加接近 `y`,最优解一定优先考虑 `x2`。
2. 在确定了 `x` 以后,以后就不用再考虑 `x` 了,因为如果 `y2 > y1`,且 `y2` 的时候取 `x` 还是一样的,那么算距离的话,`y2 - x` 显然大于 `y1 - x`,这样的话肯定不会是最短的距离。
- 从上面这两个常识来看,可以用双端队列 `deque` 来处理 `prefixSum`。`deque` 中存储的是递增的 `x` 下标,为了满足常识一。从双端队列的开头开始遍历,假如区间和之差大于等于 `K`,就移除队首元素并更新结果 `res`。队首移除元素,直到不满足 `prefixSum[i]-prefixSum[deque[0]] >= K` 这一不等式,是为了满足常识二。之后的循环是此题的精髓,从双端队列的末尾开始往前遍历,假如当前区间和 `prefixSum[i]` 小于等于队列末尾的区间和,则移除队列末尾元素。为什么这样处理呢?因为若数组都是正数,那么长度越长,区间和一定越大,则 `prefixSum[i]` 一定大于所有双端队列中的区间和,但由于可能存在负数,从而使得长度变长,区间总和反而减少了,之前的区间和之差值都没有大于等于 `K`(< K),现在的更不可能大于等于 `K`,这个结束位置可以直接淘汰,不用进行计算。循环结束后将当前位置加入双端队列即可。遇到新下标在队尾移除若干元素,这一行为,也是为了满足常识一。
- 由于所有下标都只进队列一次,也最多 pop 出去一次,所以时间复杂度 O(n),空间复杂度 O(n)。
## 代码
```go
func shortestSubarray(A []int, K int) int {
res, prefixSum := len(A)+1, make([]int, len(A)+1)
for i := 0; i < len(A); i++ {
prefixSum[i+1] = prefixSum[i] + A[i]
}
// deque 中保存递增的 prefixSum 下标
deque := []int{}
for i := range prefixSum {
// 下面这个循环希望能找到 [deque[0], i] 区间内累加和 >= K,如果找到了就更新答案
for len(deque) > 0 && prefixSum[i]-prefixSum[deque[0]] >= K {
length := i - deque[0]
if res > length {
res = length
}
// 找到第一个 deque[0] 能满足条件以后,就移除它,因为它是最短长度的子序列了
deque = deque[1:]
}
// 下面这个循环希望能保证 prefixSum[deque[i]] 递增
for len(deque) > 0 && prefixSum[i] <= prefixSum[deque[len(deque)-1]] {
deque = deque[:len(deque)-1]
}
deque = append(deque, i)
}
if res <= len(A) {
return res
}
return -1
}
```

View File

@@ -0,0 +1,61 @@
package leetcode
import (
"github.com/halfrost/LeetCode-Go/structures"
)
// TreeNode define
type TreeNode = structures.TreeNode
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func distanceK(root *TreeNode, target *TreeNode, K int) []int {
visit := []int{}
findDistanceK(root, target, K, &visit)
return visit
}
func findDistanceK(root, target *TreeNode, K int, visit *[]int) int {
if root == nil {
return -1
}
if root == target {
findChild(root, K, visit)
return K - 1
}
leftDistance := findDistanceK(root.Left, target, K, visit)
if leftDistance == 0 {
findChild(root, leftDistance, visit)
}
if leftDistance > 0 {
findChild(root.Right, leftDistance-1, visit)
return leftDistance - 1
}
rightDistance := findDistanceK(root.Right, target, K, visit)
if rightDistance == 0 {
findChild(root, rightDistance, visit)
}
if rightDistance > 0 {
findChild(root.Left, rightDistance-1, visit)
return rightDistance - 1
}
return -1
}
func findChild(root *TreeNode, K int, visit *[]int) {
if root == nil {
return
}
if K == 0 {
*visit = append(*visit, root.Val)
} else {
findChild(root.Left, K-1, visit)
findChild(root.Right, K-1, visit)
}
}

View File

@@ -0,0 +1,47 @@
package leetcode
import (
"fmt"
"testing"
"github.com/halfrost/LeetCode-Go/structures"
)
type question863 struct {
para863
ans863
}
// para 是参数
// one 代表第一个参数
type para863 struct {
root []int
target []int
K int
}
// ans 是答案
// one 代表第一个答案
type ans863 struct {
one []int
}
func Test_Problem863(t *testing.T) {
qs := []question863{
question863{
para863{[]int{3, 5, 1, 6, 2, 0, 8, structures.NULL, structures.NULL, 7, 4}, []int{5}, 2},
ans863{[]int{7, 4, 1}},
},
}
fmt.Printf("------------------------Leetcode Problem 863------------------------\n")
for _, q := range qs {
_, p := q.ans863, q.para863
tree, target := structures.Ints2TreeNode(p.root), structures.Ints2TreeNode(p.target)
fmt.Printf("【input】:%v 【output】:%v\n", p, distanceK(tree, target, p.K))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,95 @@
# 863. All Nodes Distance K in Binary Tree
## 题目
We are given a binary tree (with root node `root`), a `target` node, and an integer value `K`.
Return a list of the values of all nodes that have a distance `K` from the `target` node. The answer can be returned in any order.
**Example 1**:
```
Input: root = [3,5,1,6,2,0,8,null,null,7,4], target = 5, K = 2
Output: [7,4,1]
Explanation:
The nodes that are a distance 2 from the target node (with value 5)
have values 7, 4, and 1.
```
![https://s3-lc-upload.s3.amazonaws.com/uploads/2018/06/28/sketch0.png](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/06/28/sketch0.png)
**Note**:
1. The given tree is non-empty.
2. Each node in the tree has unique values `0 <= node.val <= 500`.
3. The `target` node is a node in the tree.
4. `0 <= K <= 1000`.
## 题目大意
给定一个二叉树(具有根结点 root), 一个目标结点 target ,和一个整数值 K 。返回到目标结点 target 距离为 K 的所有结点的值的列表。 答案可以以任何顺序返回。
提示:
- 给定的树是非空的。
- 树上的每个结点都具有唯一的值 0 <= node.val <= 500 。
- 目标结点 target 是树上的结点。
- 0 <= K <= 1000.
## 解题思路
- 给出一颗树和一个目标节点 target,一个距离 K,要求找到所有距离目标节点 target 的距离是 K 的点。
- 这一题用 DFS 的方法解题。先找到当前节点距离目标节点的距离,如果在左子树中找到了 target,距离当前节点的距离 > 0,则还需要在它的右子树中查找剩下的距离。如果是在右子树中找到了 target,反之同理。如果当前节点就是目标节点,那么就可以直接记录这个点。否则每次遍历一个点,距离都减一。
## 代码
```go
func distanceK(root *TreeNode, target *TreeNode, K int) []int {
visit := []int{}
findDistanceK(root, target, K, &visit)
return visit
}
func findDistanceK(root, target *TreeNode, K int, visit *[]int) int {
if root == nil {
return -1
}
if root == target {
findChild(root, K, visit)
return K - 1
}
leftDistance := findDistanceK(root.Left, target, K, visit)
if leftDistance == 0 {
findChild(root, leftDistance, visit)
}
if leftDistance > 0 {
findChild(root.Right, leftDistance-1, visit)
return leftDistance - 1
}
rightDistance := findDistanceK(root.Right, target, K, visit)
if rightDistance == 0 {
findChild(root, rightDistance, visit)
}
if rightDistance > 0 {
findChild(root.Left, rightDistance-1, visit)
return rightDistance - 1
}
return -1
}
func findChild(root *TreeNode, K int, visit *[]int) {
if root == nil {
return
}
if K == 0 {
*visit = append(*visit, root.Val)
} else {
findChild(root.Left, K-1, visit)
findChild(root.Right, K-1, visit)
}
}
```

View File

@@ -0,0 +1,41 @@
package leetcode
import (
"github.com/halfrost/LeetCode-Go/structures"
)
// TreeNode define
type TreeNode = structures.TreeNode
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func leafSimilar(root1 *TreeNode, root2 *TreeNode) bool {
leaf1, leaf2 := []int{}, []int{}
dfsLeaf(root1, &leaf1)
dfsLeaf(root2, &leaf2)
if len(leaf1) != len(leaf2) {
return false
}
for i := range leaf1 {
if leaf1[i] != leaf2[i] {
return false
}
}
return true
}
func dfsLeaf(root *TreeNode, leaf *[]int) {
if root != nil {
if root.Left == nil && root.Right == nil {
*leaf = append(*leaf, root.Val)
}
dfsLeaf(root.Left, leaf)
dfsLeaf(root.Right, leaf)
}
}

View File

@@ -0,0 +1,47 @@
package leetcode
import (
"fmt"
"testing"
"github.com/halfrost/LeetCode-Go/structures"
)
type question872 struct {
para872
ans872
}
// para 是参数
// one 代表第一个参数
type para872 struct {
one []int
two []int
}
// ans 是答案
// one 代表第一个答案
type ans872 struct {
one bool
}
func Test_Problem872(t *testing.T) {
qs := []question872{
question872{
para872{[]int{-10, -3, 0, 5, 9}, []int{-10, -3, 0, 5, 9}},
ans872{true},
},
}
fmt.Printf("------------------------Leetcode Problem 872------------------------\n")
for _, q := range qs {
_, p := q.ans872, q.para872
tree1 := structures.Ints2TreeNode(p.one)
tree2 := structures.Ints2TreeNode(p.two)
fmt.Printf("【input】:%v 【output】:%v\n", p, leafSimilar(tree1, tree2))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,61 @@
# 872. Leaf-Similar Trees
## 题目
Consider all the leaves of a binary tree. From left to right order, the values of those leaves form a *leaf value sequence.*
![https://s3-lc-upload.s3.amazonaws.com/uploads/2018/07/16/tree.png](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/07/16/tree.png)
For example, in the given tree above, the leaf value sequence is `(6, 7, 4, 9, 8)`.
Two binary trees are considered *leaf-similar* if their leaf value sequence is the same.
Return `true` if and only if the two given trees with head nodes `root1` and `root2` are leaf-similar.
**Note**:
- Both of the given trees will have between `1` and `100` nodes.
## 题目大意
请考虑一颗二叉树上所有的叶子,这些叶子的值按从左到右的顺序排列形成一个 叶值序列 。举个例子,如上图所示,给定一颗叶值序列为 (6, 7, 4, 9, 8) 的树。如果有两颗二叉树的叶值序列是相同,那么我们就认为它们是 叶相似 的。如果给定的两个头结点分别为 root1 和 root2 的树是叶相似的,则返回 true;否则返回 false 。
提示:
- 给定的两颗树可能会有 1 到 200 个结点。
- 给定的两颗树上的值介于 0 到 200 之间。
## 解题思路
- 给出 2 棵树,如果 2 棵树的叶子节点组成的数组是完全一样的,那么就认为这 2 棵树是“叶子相似”的。给出任何 2 棵树判断这 2 棵树是否是“叶子相似”的。
- 简单题,分别 DFS 遍历 2 棵树,把叶子节点都遍历出来,然后分别比较叶子节点组成的数组是否完全一致即可。
## 代码
```go
func leafSimilar(root1 *TreeNode, root2 *TreeNode) bool {
leaf1, leaf2 := []int{}, []int{}
dfsLeaf(root1, &leaf1)
dfsLeaf(root2, &leaf2)
if len(leaf1) != len(leaf2) {
return false
}
for i := range leaf1 {
if leaf1[i] != leaf2[i] {
return false
}
}
return true
}
func dfsLeaf(root *TreeNode, leaf *[]int) {
if root != nil {
if root.Left == nil && root.Right == nil {
*leaf = append(*leaf, root.Val)
}
dfsLeaf(root.Left, leaf)
dfsLeaf(root.Right, leaf)
}
}
```

View File

@@ -0,0 +1,28 @@
package leetcode
import "sort"
type RecentCounter struct {
list []int
}
func Constructor933() RecentCounter {
return RecentCounter{
list: []int{},
}
}
func (this *RecentCounter) Ping(t int) int {
this.list = append(this.list, t)
index := sort.Search(len(this.list), func(i int) bool { return this.list[i] >= t-3000 })
if index < 0 {
index = -index - 1
}
return len(this.list) - index
}
/**
* Your RecentCounter object will be instantiated and called as such:
* obj := Constructor();
* param_1 := obj.Ping(t);
*/

View File

@@ -0,0 +1,19 @@
package leetcode
import (
"fmt"
"testing"
)
func Test_Problem933(t *testing.T) {
obj := Constructor933()
fmt.Printf("obj = %v\n", obj)
param1 := obj.Ping(1)
fmt.Printf("param = %v\n", param1)
param1 = obj.Ping(100)
fmt.Printf("param = %v\n", param1)
param1 = obj.Ping(3001)
fmt.Printf("param = %v\n", param1)
param1 = obj.Ping(3002)
fmt.Printf("param = %v\n", param1)
}

View File

@@ -0,0 +1,73 @@
# 933. Number of Recent Calls
### 题目
Write a class `RecentCounter` to count recent requests.
It has only one method: `ping(int t)`, where t represents some time in milliseconds.
Return the number of `ping`s that have been made from 3000 milliseconds ago until now.
Any ping with time in `[t - 3000, t]` will count, including the current ping.
It is guaranteed that every call to `ping` uses a strictly larger value of `t` than before.
**Example 1**:
```
Input: inputs = ["RecentCounter","ping","ping","ping","ping"], inputs = [[],[1],[100],[3001],[3002]]
Output: [null,1,2,3,3]
```
**Note**:
1. Each test case will have at most `10000` calls to `ping`.
2. Each test case will call `ping` with strictly increasing values of `t`.
3. Each call to ping will have `1 <= t <= 10^9`.
## 题目大意
写一个 RecentCounter 类来计算最近的请求。它只有一个方法:ping(int t),其中 t 代表以毫秒为单位的某个时间。返回从 3000 毫秒前到现在的 ping 数。任何处于 [t - 3000, t] 时间范围之内的 ping 都将会被计算在内,包括当前(指 t 时刻)的 ping。保证每次对 ping 的调用都使用比之前更大的 t 值。
 
提示:
- 每个测试用例最多调用 10000 次 ping。
- 每个测试用例会使用严格递增的 t 值来调用 ping。
- 每次调用 ping 都有 1 <= t <= 10^9。
## 解题思路
- 要求设计一个类,可以用 `ping(t)` 的方法,计算 [t-3000, t] 区间内的 ping 数。t 是毫秒。
- 这一题比较简单,`ping()` 方法用二分搜索即可。
## 代码
```go
type RecentCounter struct {
list []int
}
func Constructor933() RecentCounter {
return RecentCounter{
list: []int{},
}
}
func (this *RecentCounter) Ping(t int) int {
this.list = append(this.list, t)
index := sort.Search(len(this.list), func(i int) bool { return this.list[i] >= t-3000 })
if index < 0 {
index = -index - 1
}
return len(this.list) - index
}
/**
* Your RecentCounter object will be instantiated and called as such:
* obj := Constructor();
* param_1 := obj.Ping(t);
*/
```

View File

@@ -0,0 +1,46 @@
package leetcode
var dir = [][]int{
[]int{-1, 0},
[]int{0, 1},
[]int{1, 0},
[]int{0, -1},
}
func numEnclaves(A [][]int) int {
m, n := len(A), len(A[0])
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if i == 0 || i == m-1 || j == 0 || j == n-1 {
if A[i][j] == 1 {
dfsNumEnclaves(A, i, j)
}
}
}
}
count := 0
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if A[i][j] == 1 {
count++
}
}
}
return count
}
func dfsNumEnclaves(A [][]int, x, y int) {
if !isInGrid(A, x, y) || A[x][y] == 0 {
return
}
A[x][y] = 0
for i := 0; i < 4; i++ {
nx := x + dir[i][0]
ny := y + dir[i][1]
dfsNumEnclaves(A, nx, ny)
}
}
func isInGrid(grid [][]int, x, y int) bool {
return x >= 0 && x < len(grid) && y >= 0 && y < len(grid[0])
}

View File

@@ -0,0 +1,90 @@
package leetcode
import (
"fmt"
"testing"
)
type question1020 struct {
para1020
ans1020
}
// para 是参数
// one 代表第一个参数
type para1020 struct {
one [][]int
}
// ans 是答案
// one 代表第一个答案
type ans1020 struct {
one int
}
func Test_Problem1020(t *testing.T) {
qs := []question1020{
question1020{
para1020{[][]int{
[]int{1, 1, 1, 1, 0},
[]int{1, 1, 0, 1, 0},
[]int{1, 1, 0, 0, 0},
[]int{0, 0, 0, 0, 0},
}},
ans1020{0},
},
question1020{
para1020{[][]int{
[]int{1, 1, 0, 0, 0},
[]int{1, 1, 0, 0, 0},
[]int{0, 0, 1, 0, 0},
[]int{0, 0, 0, 1, 1},
}},
ans1020{1},
},
question1020{
para1020{[][]int{
[]int{1, 1, 1, 1, 1, 1, 1, 0},
[]int{1, 0, 0, 0, 0, 1, 1, 0},
[]int{1, 0, 1, 0, 1, 1, 1, 0},
[]int{1, 0, 0, 0, 0, 1, 0, 1},
[]int{1, 1, 1, 1, 1, 1, 1, 0},
}},
ans1020{1},
},
question1020{
para1020{[][]int{
[]int{0, 0, 1, 0, 0},
[]int{0, 1, 0, 1, 0},
[]int{0, 1, 1, 1, 0},
}},
ans1020{0},
},
question1020{
para1020{[][]int{
[]int{1, 1, 1, 1, 1, 1, 1},
[]int{1, 0, 0, 0, 0, 0, 1},
[]int{1, 0, 1, 1, 1, 0, 1},
[]int{1, 0, 1, 0, 1, 0, 1},
[]int{1, 0, 1, 1, 1, 0, 1},
[]int{1, 0, 0, 0, 0, 0, 1},
[]int{1, 1, 1, 1, 1, 1, 1},
}},
ans1020{8},
},
}
fmt.Printf("------------------------Leetcode Problem 1020------------------------\n")
for _, q := range qs {
_, p := q.ans1020, q.para1020
fmt.Printf("【input】:%v 【output】:%v\n", p, numEnclaves(p.one))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,92 @@
# 1020. Number of Enclaves
## 题目
Given a 2D array `A`, each cell is 0 (representing sea) or 1 (representing land)
A move consists of walking from one land square 4-directionally to another land square, or off the boundary of the grid.
Return the number of land squares in the grid for which we **cannot** walk off the boundary of the grid in any number of moves.
**Example 1**:
```
Input: [[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]]
Output: 3
Explanation:
There are three 1s that are enclosed by 0s, and one 1 that isn't enclosed because its on the boundary.
```
**Example 2**:
```
Input: [[0,1,1,0],[0,0,1,0],[0,0,1,0],[0,0,0,0]]
Output: 0
Explanation:
All 1s are either on the boundary or can reach the boundary.
```
**Note**:
1. `1 <= A.length <= 500`
2. `1 <= A[i].length <= 500`
3. `0 <= A[i][j] <= 1`
4. All rows have the same size.
## 题目大意
给出一个二维数组 A,每个单元格为 0(代表海)或 1(代表陆地)。移动是指在陆地上从一个地方走到另一个地方(朝四个方向之一)或离开网格的边界。返回网格中无法在任意次数的移动中离开网格边界的陆地单元格的数量。
提示:
- 1 <= A.length <= 500
- 1 <= A[i].length <= 500
- 0 <= A[i][j] <= 1
- 所有行的大小都相同
## 解题思路
- 给出一个地图,要求输出不和边界连通的 1 的个数。
- 这一题可以用 DFS 也可以用并查集解答。DFS 的思路是深搜的过程中把和边界连通的点都覆盖成 0,最后遍历一遍地图,输出 1 的个数即可。并查集的思路就比较直接了,把能和边界连通的放在一个集合中,剩下的就是不能和边界连通的都在另外一个集合中,输出这个集合里面元素的个数即可。
- 这一题和第 200 题,第 1254 题,第 695 题类似。可以放在一起练习。
## 代码
```go
func numEnclaves(A [][]int) int {
m, n := len(A), len(A[0])
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if i == 0 || i == m-1 || j == 0 || j == n-1 {
if A[i][j] == 1 {
dfsNumEnclaves(A, i, j)
}
}
}
}
count := 0
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if A[i][j] == 1 {
count++
}
}
}
return count
}
func dfsNumEnclaves(A [][]int, x, y int) {
if !isInGrid(A, x, y) || A[x][y] == 0 {
return
}
A[x][y] = 0
for i := 0; i < 4; i++ {
nx := x + dir[i][0]
ny := y + dir[i][1]
dfsNumEnclaves(A, nx, ny)
}
}
```

View File

@@ -0,0 +1,61 @@
package leetcode
import (
"github.com/halfrost/LeetCode-Go/structures"
)
// TreeNode define
type TreeNode = structures.TreeNode
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func maxAncestorDiff(root *TreeNode) int {
res := 0
dfsAncestorDiff(root, &res)
return res
}
func dfsAncestorDiff(root *TreeNode, res *int) (int, int) {
if root == nil {
return -1, -1
}
leftMax, leftMin := dfsAncestorDiff(root.Left, res)
if leftMax == -1 && leftMin == -1 {
leftMax = root.Val
leftMin = root.Val
}
rightMax, rightMin := dfsAncestorDiff(root.Right, res)
if rightMax == -1 && rightMin == -1 {
rightMax = root.Val
rightMin = root.Val
}
*res = max(*res, max(abs(root.Val-min(leftMin, rightMin)), abs(root.Val-max(leftMax, rightMax))))
return max(leftMax, max(rightMax, root.Val)), min(leftMin, min(rightMin, root.Val))
}
func max(a int, b int) int {
if a > b {
return a
}
return b
}
func min(a int, b int) int {
if a > b {
return b
}
return a
}
func abs(a int) int {
if a > 0 {
return a
}
return -a
}

View File

@@ -0,0 +1,60 @@
package leetcode
import (
"fmt"
"testing"
"github.com/halfrost/LeetCode-Go/structures"
)
type question1026 struct {
para1026
ans1026
}
// para 是参数
// one 代表第一个参数
type para1026 struct {
one []int
}
// ans 是答案
// one 代表第一个答案
type ans1026 struct {
one int
}
func Test_Problem1026(t *testing.T) {
qs := []question1026{
question1026{
para1026{[]int{}},
ans1026{0},
},
question1026{
para1026{[]int{8, 3, 10, 1, 6, structures.NULL, 14, structures.NULL, structures.NULL, 4, 7, 13}},
ans1026{7},
},
question1026{
para1026{[]int{7, 6, 4, 3, 1}},
ans1026{6},
},
question1026{
para1026{[]int{1, 3, 2, 8, 4, 9}},
ans1026{8},
},
}
fmt.Printf("------------------------Leetcode Problem 1026------------------------\n")
for _, q := range qs {
_, p := q.ans1026, q.para1026
tree := structures.Ints2TreeNode(p.one)
fmt.Printf("【input】:%v 【output】:%v\n", p, maxAncestorDiff(tree))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,73 @@
# 1026. Maximum Difference Between Node and Ancestor
## 题目
Given the `root` of a binary tree, find the maximum value `V` for which there exists **different** nodes `A` and `B` where `V = |A.val - B.val|` and `A` is an ancestor of `B`.
(A node A is an ancestor of B if either: any child of A is equal to B, or any child of A is an ancestor of B.)
**Example 1**:
![https://assets.leetcode.com/uploads/2019/09/09/2whqcep.jpg](https://assets.leetcode.com/uploads/2019/09/09/2whqcep.jpg)
```
Input: [8,3,10,1,6,null,14,null,null,4,7,13]
Output: 7
Explanation:
We have various ancestor-node differences, some of which are given below :
|8 - 3| = 5
|3 - 7| = 4
|8 - 1| = 7
|10 - 13| = 3
Among all possible differences, the maximum value of 7 is obtained by |8 - 1| = 7.
```
**Note**:
1. The number of nodes in the tree is between `2` and `5000`.
2. Each node will have value between `0` and `100000`.
## 题目大意
给定二叉树的根节点 root,找出存在于不同节点 A 和 B 之间的最大值 V,其中 V = |A.val - B.val|,且 A 是 B 的祖先。(如果 A 的任何子节点之一为 B,或者 A 的任何子节点是 B 的祖先,那么我们认为 A 是 B 的祖先)
提示:
- 树中的节点数在 2 到 5000 之间。
- 每个节点的值介于 0 到 100000 之间。
## 解题思路
- 给出一颗树,要求找出祖先和孩子的最大差值。
- DPS 深搜即可。每个节点和其所有孩子的`最大值`来自于 3 个值,节点本身,递归遍历左子树的最大值,递归遍历右子树的最大值;每个节点和其所有孩子的`最小值`来自于 3 个值,节点本身,递归遍历左子树的最小值,递归遍历右子树的最小值。依次求出自身节点和其所有孩子节点的最大差值,深搜的过程中动态维护最大差值即可。
## 代码
```go
func maxAncestorDiff(root *TreeNode) int {
res := 0
dfsAncestorDiff(root, &res)
return res
}
func dfsAncestorDiff(root *TreeNode, res *int) (int, int) {
if root == nil {
return -1, -1
}
leftMax, leftMin := dfsAncestorDiff(root.Left, res)
if leftMax == -1 && leftMin == -1 {
leftMax = root.Val
leftMin = root.Val
}
rightMax, rightMin := dfsAncestorDiff(root.Right, res)
if rightMax == -1 && rightMin == -1 {
rightMax = root.Val
rightMin = root.Val
}
*res = max(*res, max(abs(root.Val-min(leftMin, rightMin)), abs(root.Val-max(leftMax, rightMax))))
return max(leftMax, max(rightMax, root.Val)), min(leftMin, min(rightMin, root.Val))
}
```

View File

@@ -45,7 +45,7 @@ Return the minimum, maximum, mean, median, and mode of the sample respectively,
- 这个问题的关键需要理解题目的意思,什么是采样?`count[k]` 就是整数 `k` 的采样个数。
- 题目要求返回样本的最小值、最大值、平均值、中位数和众数。最大值和最小值就很好处理,只需要遍历 count 判断最小的非 0 的 index 就是最小值,最大的非 0 的 index 就是最大值。平均值也非常好处理,对于所有非 0 的 count,我们通过累加 count[k] * index 得到所有数的和,然后除上所有非 0 的 count 的和。![](https://latex.codecogs.com/gif.latex?%24%24%5Csum_%7Bn%3D0%7D%5E%7B256%7Dcount%5Bn%5D%28while%5C%20%5C%20count%5Bn%5D%21%3D0%29%24%24)
- 题目要求返回样本的最小值、最大值、平均值、中位数和众数。最大值和最小值就很好处理,只需要遍历 count 判断最小的非 0 的 index 就是最小值,最大的非 0 的 index 就是最大值。平均值也非常好处理,对于所有非 0 的 count,我们通过累加 count[k] * index 得到所有数的和,然后除上所有非 0 的 count 的和。![](https://latex.codecogs.com/svg.latex?\sum_{n=0}^{256}count[n](while\%20\%20count[n]!=0))
- 众数也非常容易,只需统计 count 值最大时的 index 即可。
- 中位数的处理相对麻烦一些,因为需要分非 0 的 count 之和是奇数还是偶数两种情况。先假设非 0 的 count 和为 cnt,那么如果 cnt 是奇数的话,只需要找到 cnt/2 的位置即可,通过不断累加 count 的值,直到累加和超过 ≥ cnt/2。如果 cnt 是偶数的话,需要找到 cnt/2 + 1 和 cnt/2 的位置,找法和奇数情况相同,不过需要找两次(可以放到一个循环中做两次判断)。

View File

@@ -0,0 +1,48 @@
package leetcode
import (
"github.com/halfrost/LeetCode-Go/structures"
)
// TreeNode define
type TreeNode = structures.TreeNode
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func delNodes(root *TreeNode, toDelete []int) []*TreeNode {
if root == nil {
return nil
}
res, deleteMap := []*TreeNode{}, map[int]bool{}
for _, v := range toDelete {
deleteMap[v] = true
}
dfsDelNodes(root, deleteMap, true, &res)
return res
}
func dfsDelNodes(root *TreeNode, toDel map[int]bool, isRoot bool, res *[]*TreeNode) bool {
if root == nil {
return false
}
if isRoot && !toDel[root.Val] {
*res = append(*res, root)
}
isRoot = false
if toDel[root.Val] {
isRoot = true
}
if dfsDelNodes(root.Left, toDel, isRoot, res) {
root.Left = nil
}
if dfsDelNodes(root.Right, toDel, isRoot, res) {
root.Right = nil
}
return isRoot
}

View File

@@ -0,0 +1,46 @@
package leetcode
import (
"fmt"
"testing"
"github.com/halfrost/LeetCode-Go/structures"
)
type question1110 struct {
para1110
ans1110
}
// para 是参数
// one 代表第一个参数
type para1110 struct {
one []int
two []int
}
// ans 是答案
// one 代表第一个答案
type ans1110 struct {
one [][]int
}
func Test_Problem1110(t *testing.T) {
qs := []question1110{
question1110{
para1110{[]int{1, 2, 3, 4, 5, 6, 7}, []int{3, 5}},
ans1110{[][]int{[]int{1, 2, structures.NULL, 4}, []int{6}, []int{7}}},
},
}
fmt.Printf("------------------------Leetcode Problem 1110------------------------\n")
for _, q := range qs {
_, p := q.ans1110, q.para1110
tree := structures.Ints2TreeNode(p.one)
fmt.Printf("【input】:%v 【output】:%v\n", p, delNodes(tree, p.two))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,82 @@
# 1110. Delete Nodes And Return Forest
## 题目
Given the `root` of a binary tree, each node in the tree has a distinct value.
After deleting all nodes with a value in `to_delete`, we are left with a forest (a disjoint union of trees).
Return the roots of the trees in the remaining forest. You may return the result in any order.
**Example 1**:
![https://assets.leetcode.com/uploads/2019/07/01/screen-shot-2019-07-01-at-53836-pm.png](https://assets.leetcode.com/uploads/2019/07/01/screen-shot-2019-07-01-at-53836-pm.png)
```
Input: root = [1,2,3,4,5,6,7], to_delete = [3,5]
Output: [[1,2,null,4],[6],[7]]
```
**Constraints**:
- The number of nodes in the given tree is at most `1000`.
- Each node has a distinct value between `1` and `1000`.
- `to_delete.length <= 1000`
- `to_delete` contains distinct values between `1` and `1000`.
## 题目大意
给出二叉树的根节点 root,树上每个节点都有一个不同的值。如果节点值在 to_delete 中出现,我们就把该节点从树上删去,最后得到一个森林(一些不相交的树构成的集合)。返回森林中的每棵树。你可以按任意顺序组织答案。
提示:
- 树中的节点数最大为 1000。
- 每个节点都有一个介于 1 到 1000 之间的值,且各不相同。
- to_delete.length <= 1000
- to_delete 包含一些从 1 到 1000、各不相同的值。
## 解题思路
- 给出一棵树,再给出一个数组,要求删除数组中相同元素值的节点。输出最终删除以后的森林。
- 简单题。边遍历树,边删除数组中的元素。这里可以先把数组里面的元素放入 map 中,加速查找。遇到相同的元素就删除节点。这里需要特殊判断的是当前删除的节点是否是根节点,如果是根节点需要根据条件置空它的左节点或者右节点。
## 代码
```go
func delNodes(root *TreeNode, toDelete []int) []*TreeNode {
if root == nil {
return nil
}
res, deleteMap := []*TreeNode{}, map[int]bool{}
for _, v := range toDelete {
deleteMap[v] = true
}
dfsDelNodes(root, deleteMap, true, &res)
return res
}
func dfsDelNodes(root *TreeNode, toDel map[int]bool, isRoot bool, res *[]*TreeNode) bool {
if root == nil {
return false
}
if isRoot && !toDel[root.Val] {
*res = append(*res, root)
}
isRoot = false
if toDel[root.Val] {
isRoot = true
}
if dfsDelNodes(root.Left, toDel, isRoot, res) {
root.Left = nil
}
if dfsDelNodes(root.Right, toDel, isRoot, res) {
root.Right = nil
}
return isRoot
}
```

View File

@@ -0,0 +1,36 @@
package leetcode
import (
"github.com/halfrost/LeetCode-Go/structures"
)
// TreeNode define
type TreeNode = structures.TreeNode
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func btreeGameWinningMove(root *TreeNode, n int, x int) bool {
var left, right int
dfsBtreeGameWinningMove(root, &left, &right, x)
up := n - left - right - 1
n /= 2
return left > n || right > n || up > n
}
func dfsBtreeGameWinningMove(node *TreeNode, left, right *int, x int) int {
if node == nil {
return 0
}
l, r := dfsBtreeGameWinningMove(node.Left, left, right, x), dfsBtreeGameWinningMove(node.Right, left, right, x)
if node.Val == x {
*left, *right = l, r
}
return l + r + 1
}

View File

@@ -0,0 +1,47 @@
package leetcode
import (
"fmt"
"testing"
"github.com/halfrost/LeetCode-Go/structures"
)
type question1145 struct {
para1145
ans1145
}
// para 是参数
// one 代表第一个参数
type para1145 struct {
root []int
n int
x int
}
// ans 是答案
// one 代表第一个答案
type ans1145 struct {
one bool
}
func Test_Problem1145(t *testing.T) {
qs := []question1145{
question1145{
para1145{[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11, 3},
ans1145{true},
},
}
fmt.Printf("------------------------Leetcode Problem 1145------------------------\n")
for _, q := range qs {
_, p := q.ans1145, q.para1145
tree := structures.Ints2TreeNode(p.root)
fmt.Printf("【input】:%v 【output】:%v\n", p, btreeGameWinningMove(tree, p.n, p.x))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,81 @@
# 1145. Binary Tree Coloring Game
## 题目
Two players play a turn based game on a binary tree. We are given the `root` of this binary tree, and the number of nodes `n` in the tree. `n` is odd, and each node has a distinct value from `1` to `n`.
Initially, the first player names a value `x` with `1 <= x <= n`, and the second player names a value `y` with `1 <= y <= n` and `y != x`. The first player colors the node with value `x` red, and the second player colors the node with value `y` blue.
Then, the players take turns starting with the first player. In each turn, that player chooses a node of their color (red if player 1, blue if player 2) and colors an **uncolored** neighbor of the chosen node (either the left child, right child, or parent of the chosen node.)
If (and only if) a player cannot choose such a node in this way, they must pass their turn. If both players pass their turn, the game ends, and the winner is the player that colored more nodes.
You are the second player. If it is possible to choose such a `y` to ensure you win the game, return `true`. If it is not possible, return `false`.
**Example 1**:
![https://assets.leetcode.com/uploads/2019/08/01/1480-binary-tree-coloring-game.png](https://assets.leetcode.com/uploads/2019/08/01/1480-binary-tree-coloring-game.png)
```
Input: root = [1,2,3,4,5,6,7,8,9,10,11], n = 11, x = 3
Output: true
Explanation: The second player can choose the node with value 2.
```
**Constraints**:
- `root` is the root of a binary tree with `n` nodes and distinct node values from `1` to `n`.
- `n` is odd.
- `1 <= x <= n <= 100`
## 题目大意
有两位极客玩家参与了一场「二叉树着色」的游戏。游戏中,给出二叉树的根节点 root,树上总共有 n 个节点,且 n 为奇数,其中每个节点上的值从 1 到 n 各不相同。游戏从「一号」玩家开始(「一号」玩家为红色,「二号」玩家为蓝色),最开始时,
- 「一号」玩家从 [1, n] 中取一个值 x(1 <= x <= n);
- 「二号」玩家也从 [1, n] 中取一个值 y(1 <= y <= n)且 y != x。
- 「一号」玩家给值为 x 的节点染上红色,而「二号」玩家给值为 y 的节点染上蓝色。
之后两位玩家轮流进行操作,每一回合,玩家选择一个他之前涂好颜色的节点,将所选节点一个 未着色 的邻节点(即左右子节点、或父节点)进行染色。如果当前玩家无法找到这样的节点来染色时,他的回合就会被跳过。若两个玩家都没有可以染色的节点时,游戏结束。着色节点最多的那位玩家获得胜利 ✌️。现在,假设你是「二号」玩家,根据所给出的输入,假如存在一个 y 值可以确保你赢得这场游戏,则返回 true;若无法获胜,就请返回 false。
提示:
- 二叉树的根节点为 root,树上由 n 个节点,节点上的值从 1 到 n 各不相同。
- n 为奇数。
- 1 <= x <= n <= 100
## 解题思路
- 2 个人参加二叉树着色游戏。二叉树节点数为奇数。1 号玩家和 2 号玩家分别在二叉树上选项一个点着色。每一回合,玩家选择一个他之前涂好颜色的节点,将所选节点一个 未着色 的邻节点(即左右子节点、或父节点)进行染色。当有人不能选点着色的时候,他的那个回合会被跳过。双方都没法继续着色的时候游戏结束。着色多的人获胜。问二号玩家是否存在必胜策略?
![](https://img.halfrost.com/Leetcode/leetcode_1145.png)
- 如图所示,当一号玩家选择了一个红色的结点,可能会将二叉树切割为 3 个部分(连通分量),如果选择的是根结点,则可能是 2 个部分或 1 个部分,如果选择叶结点,则是 1 个部分。不过无论哪种情况都无关紧要,我们都可以当成 3 个部分来对待,例如一号玩家选择了一个叶结点,我们也可以把叶结点的左右两个空指针看成大小为 0 的两个部分。
- 那么二号玩家怎样选择蓝色结点才是最优呢?答案是:选择离红色结点最近,且所属连通分量规模最大的那个点。也就是示例图中的 1 号结点。如果我们选择了 1 号结点为蓝色结点,那么可以染成红色的点就只剩下 6 号点和 7 号点了,而蓝色可以把根结点和其左子树全部占据。
- 如何确定蓝色是否有必胜策略,就可以转换为,被红色点切割的三个连通分量中,是否存在一个连通分量,大小大于所有结点数目的一半。统计三个连通分量大小的过程,可以用深度优先搜索(DFS)来实现。当遍历到某一结点,其结点值等于选定的红色结点时,我们统计这个结点的左子树 `red_left` 和右子树 `red_right` 的大小,那么我们就已经找到两个连通分量的大小了,最后一个父结点连通分量的大小,可以用结点总数减去这两个连通分量大小,再减去红色所占结点,即 `parent = n - red_left - red_right - 1`。
## 代码
```go
func btreeGameWinningMove(root *TreeNode, n int, x int) bool {
var left, right int
dfsBtreeGameWinningMove(root, &left, &right, x)
up := n - left - right - 1
n /= 2
return left > n || right > n || up > n
}
func dfsBtreeGameWinningMove(node *TreeNode, left, right *int, x int) int {
if node == nil {
return 0
}
l, r := dfsBtreeGameWinningMove(node.Left, left, right, x), dfsBtreeGameWinningMove(node.Right, left, right, x)
if node.Val == x {
*left, *right = l, r
}
return l + r + 1
}
```

View File

@@ -0,0 +1,16 @@
package leetcode
func balancedStringSplit(s string) int {
count, res := 0, 0
for _, r := range s {
if r == 'R' {
count++
} else {
count--
}
if count == 0 {
res++
}
}
return res
}

View File

@@ -0,0 +1,52 @@
package leetcode
import (
"fmt"
"testing"
)
type question1221 struct {
para1221
ans1221
}
// para 是参数
// one 代表第一个参数
type para1221 struct {
s string
}
// ans 是答案
// one 代表第一个答案
type ans1221 struct {
one int
}
func Test_Problem1221(t *testing.T) {
qs := []question1221{
question1221{
para1221{"RLRRLLRLRL"},
ans1221{4},
},
question1221{
para1221{"RLLLLRRRLR"},
ans1221{3},
},
question1221{
para1221{"LLLLRRRR"},
ans1221{1},
},
}
fmt.Printf("------------------------Leetcode Problem 1221------------------------\n")
for _, q := range qs {
_, p := q.ans1221, q.para1221
fmt.Printf("【input】:%v 【output】:%v\n", p, balancedStringSplit(p.s))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,72 @@
# [1221. Split a String in Balanced Strings](https://leetcode.com/problems/split-a-string-in-balanced-strings/)
## 题目:
Balanced strings are those who have equal quantity of 'L' and 'R' characters.
Given a balanced string `s` split it in the maximum amount of balanced strings.
Return the maximum amount of splitted balanced strings.
**Example 1**:
Input: s = "RLRRLLRLRL"
Output: 4
Explanation: s can be split into "RL", "RRLL", "RL", "RL", each substring contains same number of 'L' and 'R'.
**Example 2**:
Input: s = "RLLLLRRRLR"
Output: 3
Explanation: s can be split into "RL", "LLLRRR", "LR", each substring contains same number of 'L' and 'R'.
**Example 3**:
Input: s = "LLLLRRRR"
Output: 1
Explanation: s can be split into "LLLLRRRR".
**Constraints**:
- `1 <= s.length <= 1000`
- `s[i] = 'L' or 'R'`
## 题目大意
在一个「平衡字符串」中,'L' 和 'R' 字符的数量是相同的。给出一个平衡字符串 s,请你将它分割成尽可能多的平衡字符串。返回可以通过分割得到的平衡字符串的最大数量。
提示:
- 1 <= s.length <= 1000
- s[i] = 'L' 或 'R'
## 解题思路
- 给出一个字符串,要求把这个字符串切成一些子串,这些子串中 R 和 L 的字符数是相等的。问能切成多少个满足条件的子串。
- 这道题是简单题,按照题意模拟即可。从左往右扫,遇到 `R` 就加一,遇到 `L` 就减一,当计数是 `0` 的时候就是平衡的时候,就切割。
## 代码
```go
package leetcode
func balancedStringSplit(s string) int {
count, res := 0, 0
for _, r := range s {
if r == 'R' {
count++
} else {
count--
}
if count == 0 {
res++
}
}
return res
}
```

View File

@@ -0,0 +1,14 @@
package leetcode
func checkStraightLine(coordinates [][]int) bool {
dx0 := coordinates[1][0] - coordinates[0][0]
dy0 := coordinates[1][1] - coordinates[0][1]
for i := 1; i < len(coordinates)-1; i++ {
dx := coordinates[i+1][0] - coordinates[i][0]
dy := coordinates[i+1][1] - coordinates[i][1]
if dy*dx0 != dy0*dx { // check cross product
return false
}
}
return true
}

View File

@@ -0,0 +1,47 @@
package leetcode
import (
"fmt"
"testing"
)
type question1232 struct {
para1232
ans1232
}
// para 是参数
// one 代表第一个参数
type para1232 struct {
arr [][]int
}
// ans 是答案
// one 代表第一个答案
type ans1232 struct {
one bool
}
func Test_Problem1232(t *testing.T) {
qs := []question1232{
question1232{
para1232{[][]int{[]int{1, 2}, []int{2, 3}, []int{3, 4}, []int{4, 5}, []int{5, 6}, []int{6, 7}}},
ans1232{true},
},
question1232{
para1232{[][]int{[]int{1, 1}, []int{2, 2}, []int{3, 4}, []int{4, 5}, []int{5, 6}, []int{7, 7}}},
ans1232{false},
},
}
fmt.Printf("------------------------Leetcode Problem 1232------------------------\n")
for _, q := range qs {
_, p := q.ans1232, q.para1232
fmt.Printf("【input】:%v 【output】:%v\n", p, checkStraightLine(p.arr))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,72 @@
# [1232. Check If It Is a Straight Line](https://leetcode.com/problems/check-if-it-is-a-straight-line/)
## 题目:
You are given an array `coordinates`, `coordinates[i] = [x, y]`, where `[x, y]` represents the coordinate of a point. Check if these points make a straight line in the XY plane.
**Example 1**:
![](https://img.halfrost.com/Leetcode/leetcode_1232_1.png)
Input: coordinates = [[1,2],[2,3],[3,4],[4,5],[5,6],[6,7]]
Output: true
**Example 2**:
![](https://img.halfrost.com/Leetcode/leetcode_1232_2.png)
Input: coordinates = [[1,1],[2,2],[3,4],[4,5],[5,6],[7,7]]
Output: false
**Constraints**:
- `2 <= coordinates.length <= 1000`
- `coordinates[i].length == 2`
- `-10^4 <= coordinates[i][0], coordinates[i][1] <= 10^4`
- `coordinates` contains no duplicate point.
## 题目大意
在一个 XY 坐标系中有一些点,我们用数组 coordinates 来分别记录它们的坐标,其中 coordinates[i] = [x, y] 表示横坐标为 x、纵坐标为 y 的点。
请你来判断,这些点是否在该坐标系中属于同一条直线上,是则返回 true,否则请返回 false。
提示:
- 2 <= coordinates.length <= 1000
- coordinates[i].length == 2
- -10^4 <= coordinates[i][0], coordinates[i][1] <= 10^4
- coordinates 中不含重复的点
## 解题思路
- 给出一组坐标点,要求判断这些点是否在同一直线上。
- 按照几何原理,依次计算这些点的斜率是否相等即可。斜率需要做除法,这里采用一个技巧是换成乘法。例如 `a/b = c/d` 换成乘法是 `a*d = c*d` 。
## 代码
```go
package leetcode
func checkStraightLine(coordinates [][]int) bool {
dx0 := coordinates[1][0] - coordinates[0][0]
dy0 := coordinates[1][1] - coordinates[0][1]
for i := 1; i < len(coordinates)-1; i++ {
dx := coordinates[i+1][0] - coordinates[i][0]
dy := coordinates[i+1][1] - coordinates[i][1]
if dy*dx0 != dy0*dx { // check cross product
return false
}
}
return true
}
```

View File

@@ -0,0 +1,31 @@
package leetcode
func balancedString(s string) int {
count, k := make([]int, 128), len(s)/4
for _, v := range s {
count[int(v)]++
}
left, right, res := 0, -1, len(s)
for left < len(s) {
if count['Q'] > k || count['W'] > k || count['E'] > k || count['R'] > k {
if right+1 < len(s) {
right++
count[s[right]]--
} else {
break
}
} else {
res = min(res, right-left+1)
count[s[left]]++
left++
}
}
return res
}
func min(a int, b int) int {
if a > b {
return b
}
return a
}

View File

@@ -0,0 +1,62 @@
package leetcode
import (
"fmt"
"testing"
)
type question1234 struct {
para1234
ans1234
}
// para 是参数
// one 代表第一个参数
type para1234 struct {
s string
}
// ans 是答案
// one 代表第一个答案
type ans1234 struct {
one int
}
func Test_Problem1234(t *testing.T) {
qs := []question1234{
question1234{
para1234{"QWER"},
ans1234{0},
},
question1234{
para1234{"QQWE"},
ans1234{1},
},
question1234{
para1234{"QQQW"},
ans1234{2},
},
question1234{
para1234{"QQQQ"},
ans1234{3},
},
question1234{
para1234{"WQWRQQQW"},
ans1234{3},
},
}
fmt.Printf("------------------------Leetcode Problem 1234------------------------\n")
for _, q := range qs {
_, p := q.ans1234, q.para1234
fmt.Printf("【input】:%v 【output】:%v\n", p, balancedString(p.s))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,92 @@
# [1234. Replace the Substring for Balanced String](https://leetcode.com/problems/replace-the-substring-for-balanced-string/)
## 题目:
You are given a string containing only 4 kinds of characters `'Q',` `'W', 'E'` and `'R'`.
A string is said to be **balanced** **if each of its characters appears `n/4` times where `n` is the length of the string.
Return the minimum length of the substring that can be replaced with **any** other string of the same length to make the original string `s` **balanced**.
Return 0 if the string is already **balanced**.
**Example 1**:
Input: s = "QWER"
Output: 0
Explanation: s is already balanced.
**Example 2**:
Input: s = "QQWE"
Output: 1
Explanation: We need to replace a 'Q' to 'R', so that "RQWE" (or "QRWE") is balanced.
**Example 3**:
Input: s = "QQQW"
Output: 2
Explanation: We can replace the first "QQ" to "ER".
**Example 4**:
Input: s = "QQQQ"
Output: 3
Explanation: We can replace the last 3 'Q' to make s = "QWER".
**Constraints**:
- `1 <= s.length <= 10^5`
- `s.length` is a multiple of `4`
- `s` contains only `'Q'`, `'W'`, `'E'` and `'R'`.
## 题目大意
有一个只含有 'Q', 'W', 'E', 'R' 四种字符,且长度为 n 的字符串。假如在该字符串中,这四个字符都恰好出现 n/4 次,那么它就是一个「平衡字符串」。给你一个这样的字符串 s,请通过「替换一个子串」的方式,使原字符串 s 变成一个「平衡字符串」。你可以用和「待替换子串」长度相同的 任何 其他字符串来完成替换。请返回待替换子串的最小可能长度。如果原字符串自身就是一个平衡字符串,则返回 0。
提示:
- 1 <= s.length <= 10^5
- s.length 是 4 的倍数
- s 中只含有 'Q', 'W', 'E', 'R' 四种字符
## 解题思路
- 给出一个字符串,要求输出把这个字符串变成“平衡字符串”的最小替换字符串的长度(替换只能替换一串,不能单个字母替换)。“平衡字符串”的定义是:字符串中,`‘Q’`,`‘W’`,`‘E’`,`‘R’`,出现的次数当且仅当只有 `len(s)/4` 次。
- 这一题是滑动窗口的题目。先统计 4 个字母的频次并计算出 `k = len(s)/4` 。滑动窗口向右滑动一次,对应右窗口的那个字母频次减 1,直到滑到所有字母的频次都 `≤ k` 的地方停止。此时,窗口外的字母的频次都 `≤ k` 了。这是只要变换窗口内字符串即可。但是这个窗口内还可能包含本来频次就小于 `k` 的字母,如果能把它们剔除掉,窗口可以进一步的减少。所以继续移动左边界,试探移动完左边界以后,是否所有字母频次都 `≤ k`。在所有窗口移动过程中取出最小值,即为最终答案。
- 举个例子:`"WQWRQQQW"`。`w` 有 3 个,`Q` 有 4 个,`R` 有 1 个,`E` 有 0 个。最后平衡状态是每个字母 2 个,那么我们需要拿出 1 个 `W` 和 2 个 `Q` 替换掉。即要找到一个最短的字符串包含 1 个 `W` 和 2 个 `Q`。滑动窗口正好可以解决这个问题。向右滑到 `"WQWRQ"` 停止,这时窗口外的所有字母频次都 `≤ k` 了。这个窗口包含了多余的 1 个 `W`,和 1 个 `R`。`W` 可以踢除掉,那么要替换的字符串是 `"QWRQ"`。`R` 不能踢除了(因为要找包含 1 个 `W` 和 2 个 `Q` 的字符串) 。窗口不断的滑动,直到结束。这个例子中最小的字符串其实位于末尾,`"QQW"`。
## 代码
```go
package leetcode
func balancedString(s string) int {
count, k := make([]int, 128), len(s)/4
for _, v := range s {
count[int(v)]++
}
left, right, res := 0, -1, len(s)
for left < len(s) {
if count['Q'] > k || count['W'] > k || count['E'] > k || count['R'] > k {
if right+1 < len(s) {
right++
count[s[right]]--
} else {
break
}
} else {
res = min(res, right-left+1)
count[s[left]]++
left++
}
}
return res
}
```

View File

@@ -0,0 +1,42 @@
package leetcode
// 解法一 暴力法
func oddCells(n int, m int, indices [][]int) int {
matrix, res := make([][]int, n), 0
for i := range matrix {
matrix[i] = make([]int, m)
}
for _, indice := range indices {
for i := 0; i < m; i++ {
matrix[indice[0]][i]++
}
for j := 0; j < n; j++ {
matrix[j][indice[1]]++
}
}
for _, m := range matrix {
for _, v := range m {
if v&1 == 1 {
res++
}
}
}
return res
}
// 解法二 暴力法
func oddCells1(n int, m int, indices [][]int) int {
rows, cols, count := make([]int, n), make([]int, m), 0
for _, pair := range indices {
rows[pair[0]]++
cols[pair[1]]++
}
for i := 0; i < n; i++ {
for j := 0; j < m; j++ {
if (rows[i]+cols[j])%2 == 1 {
count++
}
}
}
return count
}

View File

@@ -0,0 +1,49 @@
package leetcode
import (
"fmt"
"testing"
)
type question1252 struct {
para1252
ans1252
}
// para 是参数
// one 代表第一个参数
type para1252 struct {
n int
m int
indices [][]int
}
// ans 是答案
// one 代表第一个答案
type ans1252 struct {
one int
}
func Test_Problem1252(t *testing.T) {
qs := []question1252{
question1252{
para1252{2, 3, [][]int{[]int{0, 1}, []int{1, 1}}},
ans1252{6},
},
question1252{
para1252{2, 2, [][]int{[]int{1, 1}, []int{0, 0}}},
ans1252{0},
},
}
fmt.Printf("------------------------Leetcode Problem 1252------------------------\n")
for _, q := range qs {
_, p := q.ans1252, q.para1252
fmt.Printf("【input】:%v 【output】:%v\n", p, oddCells(p.n, p.m, p.indices))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,102 @@
# [1252. Cells with Odd Values in a Matrix](https://leetcode.com/problems/cells-with-odd-values-in-a-matrix/)
## 题目:
Given `n` and `m` which are the dimensions of a matrix initialized by zeros and given an array `indices` where `indices[i] = [ri, ci]`. For each pair of `[ri, ci]` you have to increment all cells in row `ri` and column `ci` by 1.
Return *the number of cells with odd values* in the matrix after applying the increment to all `indices`.
**Example 1**:
![https://assets.leetcode.com/uploads/2019/10/30/e1.png](https://assets.leetcode.com/uploads/2019/10/30/e1.png)
Input: n = 2, m = 3, indices = [[0,1],[1,1]]
Output: 6
Explanation: Initial matrix = [[0,0,0],[0,0,0]].
After applying first increment it becomes [[1,2,1],[0,1,0]].
The final matrix will be [[1,3,1],[1,3,1]] which contains 6 odd numbers.
**Example 2**:
![https://assets.leetcode.com/uploads/2019/10/30/e2.png](https://assets.leetcode.com/uploads/2019/10/30/e2.png)
Input: n = 2, m = 2, indices = [[1,1],[0,0]]
Output: 0
Explanation: Final matrix = [[2,2],[2,2]]. There is no odd number in the final matrix.
**Constraints**:
- `1 <= n <= 50`
- `1 <= m <= 50`
- `1 <= indices.length <= 100`
- `0 <= indices[i][0] < n`
- `0 <= indices[i][1] < m`
## 题目大意
给你一个 n 行 m 列的矩阵,最开始的时候,每个单元格中的值都是 0。另有一个索引数组 indices,indices[i] = [ri, ci] 中的 ri 和 ci 分别表示指定的行和列(从 0 开始编号)。你需要将每对 [ri, ci] 指定的行和列上的所有单元格的值加 1。请你在执行完所有 indices 指定的增量操作后,返回矩阵中 「奇数值单元格」 的数目。
提示:
- 1 <= n <= 50
- 1 <= m <= 50
- 1 <= indices.length <= 100
- 0 <= indices[i][0] < n
- 0 <= indices[i][1] < m
## 解题思路
- 给出一个 n * m 的矩阵,和一个数组,数组里面包含一些行列坐标,并在指定坐标上 + 1,问最后 n * m 的矩阵中奇数的总数。
- 暴力方法按照题意模拟即可。
## 代码
```go
package leetcode
// 解法一 暴力法
func oddCells(n int, m int, indices [][]int) int {
matrix, res := make([][]int, n), 0
for i := range matrix {
matrix[i] = make([]int, m)
}
for _, indice := range indices {
for i := 0; i < m; i++ {
matrix[indice[0]][i]++
}
for j := 0; j < n; j++ {
matrix[j][indice[1]]++
}
}
for _, m := range matrix {
for _, v := range m {
if v&1 == 1 {
res++
}
}
}
return res
}
// 解法二 暴力法
func oddCells1(n int, m int, indices [][]int) int {
rows, cols, count := make([]int, n), make([]int, m), 0
for _, pair := range indices {
rows[pair[0]]++
cols[pair[1]]++
}
for i := 0; i < n; i++ {
for j := 0; j < m; j++ {
if (rows[i]+cols[j])%2 == 1 {
count++
}
}
}
return count
}
```

View File

@@ -0,0 +1,55 @@
package leetcode
var dir = [][]int{
[]int{-1, 0},
[]int{0, 1},
[]int{1, 0},
[]int{0, -1},
}
func closedIsland(grid [][]int) int {
m := len(grid)
if m == 0 {
return 0
}
n := len(grid[0])
if n == 0 {
return 0
}
res, visited := 0, make([][]bool, m)
for i := 0; i < m; i++ {
visited[i] = make([]bool, n)
}
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
isEdge := false
if grid[i][j] == 0 && !visited[i][j] {
checkIslands(grid, &visited, i, j, &isEdge)
if !isEdge {
res++
}
}
}
}
return res
}
func checkIslands(grid [][]int, visited *[][]bool, x, y int, isEdge *bool) {
if (x == 0 || x == len(grid)-1 || y == 0 || y == len(grid[0])-1) && grid[x][y] == 0 {
*isEdge = true
}
(*visited)[x][y] = true
for i := 0; i < 4; i++ {
nx := x + dir[i][0]
ny := y + dir[i][1]
if isIntInBoard(grid, nx, ny) && !(*visited)[nx][ny] && grid[nx][ny] == 0 {
checkIslands(grid, visited, nx, ny, isEdge)
}
}
*isEdge = *isEdge || false
}
func isIntInBoard(board [][]int, x, y int) bool {
return x >= 0 && x < len(board) && y >= 0 && y < len(board[0])
}

View File

@@ -0,0 +1,90 @@
package leetcode
import (
"fmt"
"testing"
)
type question1254 struct {
para1254
ans1254
}
// para 是参数
// one 代表第一个参数
type para1254 struct {
one [][]int
}
// ans 是答案
// one 代表第一个答案
type ans1254 struct {
one int
}
func Test_Problem1254(t *testing.T) {
qs := []question1254{
question1254{
para1254{[][]int{
[]int{1, 1, 1, 1, 0},
[]int{1, 1, 0, 1, 0},
[]int{1, 1, 0, 0, 0},
[]int{0, 0, 0, 0, 0},
}},
ans1254{0},
},
question1254{
para1254{[][]int{
[]int{1, 1, 0, 0, 0},
[]int{1, 1, 0, 0, 0},
[]int{0, 0, 1, 0, 0},
[]int{0, 0, 0, 1, 1},
}},
ans1254{0},
},
question1254{
para1254{[][]int{
[]int{1, 1, 1, 1, 1, 1, 1, 0},
[]int{1, 0, 0, 0, 0, 1, 1, 0},
[]int{1, 0, 1, 0, 1, 1, 1, 0},
[]int{1, 0, 0, 0, 0, 1, 0, 1},
[]int{1, 1, 1, 1, 1, 1, 1, 0},
}},
ans1254{2},
},
question1254{
para1254{[][]int{
[]int{0, 0, 1, 0, 0},
[]int{0, 1, 0, 1, 0},
[]int{0, 1, 1, 1, 0},
}},
ans1254{1},
},
question1254{
para1254{[][]int{
[]int{1, 1, 1, 1, 1, 1, 1},
[]int{1, 0, 0, 0, 0, 0, 1},
[]int{1, 0, 1, 1, 1, 0, 1},
[]int{1, 0, 1, 0, 1, 0, 1},
[]int{1, 0, 1, 1, 1, 0, 1},
[]int{1, 0, 0, 0, 0, 0, 1},
[]int{1, 1, 1, 1, 1, 1, 1},
}},
ans1254{2},
},
}
fmt.Printf("------------------------Leetcode Problem 1254------------------------\n")
for _, q := range qs {
_, p := q.ans1254, q.para1254
fmt.Printf("【input】:%v 【output】:%v\n", p, closedIsland(p.one))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,110 @@
# [1254. Number of Closed Islands](https://leetcode.com/problems/number-of-closed-islands/)
## 题目:
Given a 2D `grid` consists of `0s` (land) and `1s` (water). An *island* is a maximal 4-directionally connected group of `0s` and a *closed island* is an island **totally** (all left, top, right, bottom) surrounded by `1s.`
Return the number of *closed islands*.
**Example 1**:
![https://assets.leetcode.com/uploads/2019/10/31/sample_3_1610.png](https://assets.leetcode.com/uploads/2019/10/31/sample_3_1610.png)
Input: grid = [[1,1,1,1,1,1,1,0],[1,0,0,0,0,1,1,0],[1,0,1,0,1,1,1,0],[1,0,0,0,0,1,0,1],[1,1,1,1,1,1,1,0]]
Output: 2
Explanation:
Islands in gray are closed because they are completely surrounded by water (group of 1s).
**Example 2**:
![https://assets.leetcode.com/uploads/2019/10/31/sample_4_1610.png](https://assets.leetcode.com/uploads/2019/10/31/sample_4_1610.png)
Input: grid = [[0,0,1,0,0],[0,1,0,1,0],[0,1,1,1,0]]
Output: 1
**Example 3**:
Input: grid = [[1,1,1,1,1,1,1],
[1,0,0,0,0,0,1],
[1,0,1,1,1,0,1],
[1,0,1,0,1,0,1],
[1,0,1,1,1,0,1],
[1,0,0,0,0,0,1],
[1,1,1,1,1,1,1]]
Output: 2
**Constraints**:
- `1 <= grid.length, grid[0].length <= 100`
- `0 <= grid[i][j] <=1`
## 题目大意
有一个二维矩阵 grid ,每个位置要么是陆地(记号为 0 )要么是水域(记号为 1 )。我们从一块陆地出发,每次可以往上下左右 4 个方向相邻区域走,能走到的所有陆地区域,我们将其称为一座「岛屿」。如果一座岛屿 完全 由水域包围,即陆地边缘上下左右所有相邻区域都是水域,那么我们将其称为 「封闭岛屿」。请返回封闭岛屿的数目。
提示:
- 1 <= grid.length, grid[0].length <= 100
- 0 <= grid[i][j] <=1
## 解题思路
- 给出一个地图,1 代表海水,0 代表陆地。要求找出四周都是海水的陆地的总个数。
- 这一题和第 200 题解题思路完全一致。只不过这一题要求必须四周都是海水,第 200 题的陆地可以是靠着地图边缘的。在此题中,靠着地图边缘的陆地不能最终计数到结果中。
## 代码
```go
package leetcode
func closedIsland(grid [][]int) int {
m := len(grid)
if m == 0 {
return 0
}
n := len(grid[0])
if n == 0 {
return 0
}
res, visited := 0, make([][]bool, m)
for i := 0; i < m; i++ {
visited[i] = make([]bool, n)
}
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
isEdge := false
if grid[i][j] == 0 && !visited[i][j] {
checkIslands(grid, &visited, i, j, &isEdge)
if !isEdge {
res++
}
}
}
}
return res
}
func checkIslands(grid [][]int, visited *[][]bool, x, y int, isEdge *bool) {
if (x == 0 || x == len(grid)-1 || y == 0 || y == len(grid[0])-1) && grid[x][y] == 0 {
*isEdge = true
}
(*visited)[x][y] = true
for i := 0; i < 4; i++ {
nx := x + dir[i][0]
ny := y + dir[i][1]
if isIntInBoard(grid, nx, ny) && !(*visited)[nx][ny] && grid[nx][ny] == 0 {
checkIslands(grid, visited, nx, ny, isEdge)
}
}
*isEdge = *isEdge || false
}
func isIntInBoard(board [][]int, x, y int) bool {
return x >= 0 && x < len(board) && y >= 0 && y < len(board[0])
}
```

View File

@@ -0,0 +1,23 @@
package leetcode
func minTimeToVisitAllPoints(points [][]int) int {
res := 0
for i := 1; i < len(points); i++ {
res += max(abs(points[i][0]-points[i-1][0]), abs(points[i][1]-points[i-1][1]))
}
return res
}
func max(a int, b int) int {
if a > b {
return a
}
return b
}
func abs(a int) int {
if a > 0 {
return a
}
return -a
}

View File

@@ -0,0 +1,47 @@
package leetcode
import (
"fmt"
"testing"
)
type question1266 struct {
para1266
ans1266
}
// para 是参数
// one 代表第一个参数
type para1266 struct {
points [][]int
}
// ans 是答案
// one 代表第一个答案
type ans1266 struct {
one int
}
func Test_Problem1266(t *testing.T) {
qs := []question1266{
question1266{
para1266{[][]int{[]int{1, 1}, []int{3, 4}, []int{-1, 0}}},
ans1266{7},
},
question1266{
para1266{[][]int{[]int{3, 2}, []int{-2, 2}}},
ans1266{5},
},
}
fmt.Printf("------------------------Leetcode Problem 1266------------------------\n")
for _, q := range qs {
_, p := q.ans1266, q.para1266
fmt.Printf("【input】:%v 【output】:%v\n", p, minTimeToVisitAllPoints(p.points))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,74 @@
# [1266. Minimum Time Visiting All Points](https://leetcode.com/problems/minimum-time-visiting-all-points/)
## 题目:
On a plane there are `n` points with integer coordinates `points[i] = [xi, yi]`. Your task is to find the minimum time in seconds to visit all points.
You can move according to the next rules:
- In one second always you can either move vertically, horizontally by one unit or diagonally (it means to move one unit vertically and one unit horizontally in one second).
- You have to visit the points in the same order as they appear in the array.
**Example 1:**
![https://assets.leetcode.com/uploads/2019/11/14/1626_example_1.PNG](https://assets.leetcode.com/uploads/2019/11/14/1626_example_1.PNG)
Input: points = [[1,1],[3,4],[-1,0]]
Output: 7
Explanation: One optimal path is [1,1] -> [2,2] -> [3,3] -> [3,4] -> [2,3] -> [1,2] -> [0,1] -> [-1,0]
Time from [1,1] to [3,4] = 3 seconds
Time from [3,4] to [-1,0] = 4 seconds
Total time = 7 seconds
**Example 2:**
Input: points = [[3,2],[-2,2]]
Output: 5
**Constraints:**
- `points.length == n`
- `1 <= n <= 100`
- `points[i].length == 2`
- `-1000 <= points[i][0], points[i][1] <= 1000`
## 题目大意
平面上有 n 个点,点的位置用整数坐标表示 points[i] = [xi, yi]。请你计算访问所有这些点需要的最小时间(以秒为单位)。你可以按照下面的规则在平面上移动:
- 每一秒沿水平或者竖直方向移动一个单位长度,或者跨过对角线(可以看作在一秒内向水平和竖直方向各移动一个单位长度)。
- 必须按照数组中出现的顺序来访问这些点。
提示:
- points.length == n
- 1 <= n <= 100
- points[i].length == 2
- -1000 <= points[i][0], points[i][1] <= 1000
## 解题思路
- 在直角坐标系上给出一个数组,数组里面的点是飞机飞行经过的点。飞机飞行只能沿着水平方向、垂直方向、45°方向飞行。问飞机经过所有点的最短时间。
- 简单的数学问题。依次遍历数组,分别计算 x 轴和 y 轴上的差值,取最大值即是这两点之间飞行的最短时间。最后累加每次计算的最大值就是最短时间。
## 代码
```go
package leetcode
func minTimeToVisitAllPoints(points [][]int) int {
res := 0
for i := 1; i < len(points); i++ {
res += max(abs(points[i][0]-points[i-1][0]), abs(points[i][1]-points[i-1][1]))
}
return res
}
```

View File

@@ -0,0 +1,10 @@
package leetcode
func subtractProductAndSum(n int) int {
sum, product := 0, 1
for ; n > 0; n /= 10 {
sum += n % 10
product *= n % 10
}
return product - sum
}

View File

@@ -0,0 +1,47 @@
package leetcode
import (
"fmt"
"testing"
)
type question1281 struct {
para1281
ans1281
}
// para 是参数
// one 代表第一个参数
type para1281 struct {
n int
}
// ans 是答案
// one 代表第一个答案
type ans1281 struct {
one int
}
func Test_Problem1281(t *testing.T) {
qs := []question1281{
question1281{
para1281{234},
ans1281{15},
},
question1281{
para1281{4421},
ans1281{21},
},
}
fmt.Printf("------------------------Leetcode Problem 1281------------------------\n")
for _, q := range qs {
_, p := q.ans1281, q.para1281
fmt.Printf("【input】:%v 【output】:%v\n", p, subtractProductAndSum(p.n))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,58 @@
# 1281. Subtract the Product and Sum of Digits of an Integer
## 题目
Given an integer number `n`, return the difference between the product of its digits and the sum of its digits.
**Example 1**:
```
Input: n = 234
Output: 15
Explanation:
Product of digits = 2 * 3 * 4 = 24
Sum of digits = 2 + 3 + 4 = 9
Result = 24 - 9 = 15
```
**Example 2**:
```
Input: n = 4421
Output: 21
Explanation:
Product of digits = 4 * 4 * 2 * 1 = 32
Sum of digits = 4 + 4 + 2 + 1 = 11
Result = 32 - 11 = 21
```
**Constraints**:
- `1 <= n <= 10^5`
## 题目大意
给你一个整数 n,请你帮忙计算并返回该整数「各位数字之积」与「各位数字之和」的差。
提示:
- 1 <= n <= 10^5
## 解题思路
- 给出一个数,计算这个数每位数字乘积减去每位数字累加的差值。
- 简单题,按照题意输入输出即可。
## 代码
```go
func subtractProductAndSum(n int) int {
sum, product := 0, 1
for ; n > 0; n /= 10 {
sum += n % 10
product *= n % 10
}
return product - sum
}
```

View File

@@ -0,0 +1,29 @@
package leetcode
func smallestDivisor(nums []int, threshold int) int {
low, high := 1, 1000000
for low < high {
mid := low + (high-low)>>1
if calDivisor(nums, mid, threshold) {
high = mid
} else {
low = mid + 1
}
}
return low
}
func calDivisor(nums []int, mid, threshold int) bool {
sum := 0
for i := range nums {
if nums[i]%mid != 0 {
sum += nums[i]/mid + 1
} else {
sum += nums[i] / mid
}
}
if sum <= threshold {
return true
}
return false
}

View File

@@ -0,0 +1,53 @@
package leetcode
import (
"fmt"
"testing"
)
type question1283 struct {
para1283
ans1283
}
// para 是参数
// one 代表第一个参数
type para1283 struct {
nums []int
threshold int
}
// ans 是答案
// one 代表第一个答案
type ans1283 struct {
one int
}
func Test_Problem1283(t *testing.T) {
qs := []question1283{
question1283{
para1283{[]int{1, 2, 5, 9}, 6},
ans1283{5},
},
question1283{
para1283{[]int{2, 3, 5, 7, 11}, 11},
ans1283{3},
},
question1283{
para1283{[]int{19}, 5},
ans1283{4},
},
}
fmt.Printf("------------------------Leetcode Problem 1283------------------------\n")
for _, q := range qs {
_, p := q.ans1283, q.para1283
fmt.Printf("【input】:%v 【output】:%v\n", p, smallestDivisor(p.nums, p.threshold))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,86 @@
# 1283. Find the Smallest Divisor Given a Threshold
## 题目
Given an array of integers `nums` and an integer `threshold`, we will choose a positive integer divisor and divide all the array by it and sum the result of the division. Find the **smallest** divisor such that the result mentioned above is less than or equal to `threshold`.
Each result of division is rounded to the nearest integer greater than or equal to that element. (For example: 7/3 = 3 and 10/2 = 5).
It is guaranteed that there will be an answer.
**Example 1**:
```
Input: nums = [1,2,5,9], threshold = 6
Output: 5
Explanation: We can get a sum to 17 (1+2+5+9) if the divisor is 1.
If the divisor is 4 we can get a sum to 7 (1+1+2+3) and if the divisor is 5 the sum will be 5 (1+1+1+2).
```
**Example 2**:
```
Input: nums = [2,3,5,7,11], threshold = 11
Output: 3
```
**Example 3**:
```
Input: nums = [19], threshold = 5
Output: 4
```
**Constraints**:
- `1 <= nums.length <= 5 * 10^4`
- `1 <= nums[i] <= 10^6`
- `nums.length <= threshold <= 10^6`
## 题目大意
给你一个整数数组 nums 和一个正整数 threshold  ,你需要选择一个正整数作为除数,然后将数组里每个数都除以它,并对除法结果求和。请你找出能够使上述结果小于等于阈值 threshold 的除数中 最小 的那个。每个数除以除数后都向上取整,比方说 7/3 = 3 , 10/2 = 5 。题目保证一定有解。
提示:
- 1 <= nums.length <= 5 * 10^4
- 1 <= nums[i] <= 10^6
- nums.length <= threshold <= 10^6
## 解题思路
- 给出一个数组和一个阈值,要求找到一个除数,使得数组里面每个数和这个除数的商之和不超过这个阈值。求除数的最小值。
- 这一题是典型的二分搜索的题目。根据题意,在 [1, 1000000] 区间内搜索除数,针对每次 `mid`,计算一次商的累加和。如果和比 `threshold` 小,说明除数太大,所以缩小右区间;如果和比 `threshold` 大,说明除数太小,所以缩小左区间。最终找到的 `low` 值就是最求的最小除数。
## 代码
```go
func smallestDivisor(nums []int, threshold int) int {
low, high := 1, 1000000
for low < high {
mid := low + (high-low)>>1
if calDivisor(nums, mid, threshold) {
high = mid
} else {
low = mid + 1
}
}
return low
}
func calDivisor(nums []int, mid, threshold int) bool {
sum := 0
for i := range nums {
if nums[i]%mid != 0 {
sum += nums[i]/mid + 1
} else {
sum += nums[i] / mid
}
}
if sum <= threshold {
return true
}
return false
}
```

View File

@@ -0,0 +1,11 @@
package leetcode
func findSpecialInteger(arr []int) int {
n := len(arr)
for i := 0; i < n-n/4; i++ {
if arr[i] == arr[i+n/4] {
return arr[i]
}
}
return -1
}

View File

@@ -0,0 +1,42 @@
package leetcode
import (
"fmt"
"testing"
)
type question1287 struct {
para1287
ans1287
}
// para 是参数
// one 代表第一个参数
type para1287 struct {
one []int
}
// ans 是答案
// one 代表第一个答案
type ans1287 struct {
one int
}
func Test_Problem1287(t *testing.T) {
qs := []question1287{
question1287{
para1287{[]int{1, 2, 2, 6, 6, 6, 6, 7, 10}},
ans1287{6},
},
}
fmt.Printf("------------------------Leetcode Problem 1287------------------------\n")
for _, q := range qs {
_, p := q.ans1287, q.para1287
fmt.Printf("【input】:%v 【output】:%v\n", p, findSpecialInteger(p.one))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,48 @@
# 1287. Element Appearing More Than 25% In Sorted Array
## 题目
Given an integer array **sorted** in non-decreasing order, there is exactly one integer in the array that occurs more than 25% of the time.
Return that integer.
**Example 1**:
```
Input: arr = [1,2,2,6,6,6,6,7,10]
Output: 6
```
**Constraints**:
- `1 <= arr.length <= 10^4`
- `0 <= arr[i] <= 10^5`
## 题目大意
给你一个非递减的 有序 整数数组,已知这个数组中恰好有一个整数,它的出现次数超过数组元素总数的 25%。请你找到并返回这个整数。
提示:
- 1 <= arr.length <= 10^4
- 0 <= arr[i] <= 10^5
## 解题思路
- 给出一个非递减的有序数组,要求输出出现次数超过数组元素总数 25% 的元素。
- 简单题,由于已经非递减有序了,所以只需要判断 `arr[i] == arr[i+n/4]` 是否相等即可。
## 代码
```go
func findSpecialInteger(arr []int) int {
n := len(arr)
for i := 0; i < n-n/4; i++ {
if arr[i] == arr[i+n/4] {
return arr[i]
}
}
return -1
}
```

View File

@@ -0,0 +1,24 @@
package leetcode
import (
"github.com/halfrost/LeetCode-Go/structures"
)
// ListNode define
type ListNode = structures.ListNode
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func getDecimalValue(head *ListNode) int {
sum := 0
for head != nil {
sum = sum*2 + head.Val
head = head.Next
}
return sum
}

View File

@@ -0,0 +1,64 @@
package leetcode
import (
"fmt"
"testing"
"github.com/halfrost/LeetCode-Go/structures"
)
type question1290 struct {
para1290
ans1290
}
// para 是参数
// one 代表第一个参数
type para1290 struct {
one []int
}
// ans 是答案
// one 代表第一个答案
type ans1290 struct {
one int
}
func Test_Problem1290(t *testing.T) {
qs := []question1290{
question1290{
para1290{[]int{1, 0, 1}},
ans1290{5},
},
question1290{
para1290{[]int{0}},
ans1290{0},
},
question1290{
para1290{[]int{1}},
ans1290{1},
},
question1290{
para1290{[]int{0, 0}},
ans1290{0},
},
question1290{
para1290{[]int{1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}},
ans1290{18880},
},
}
fmt.Printf("------------------------Leetcode Problem 1290------------------------\n")
for _, q := range qs {
_, p := q.ans1290, q.para1290
fmt.Printf("【input】:%v 【output】:%v\n", p, getDecimalValue(structures.Ints2List(p.one)))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,80 @@
# 1290. Convert Binary Number in a Linked List to Integer
## 题目
Given `head` which is a reference node to a singly-linked list. The value of each node in the linked list is either 0 or 1. The linked list holds the binary representation of a number.
Return the *decimal value* of the number in the linked list.
**Example 1**:
![https://assets.leetcode.com/uploads/2019/12/05/graph-1.png](https://assets.leetcode.com/uploads/2019/12/05/graph-1.png)
```
Input: head = [1,0,1]
Output: 5
Explanation: (101) in base 2 = (5) in base 10
```
**Example 2**:
```
Input: head = [0]
Output: 0
```
**Example 3**:
```
Input: head = [1]
Output: 1
```
**Example 4**:
```
Input: head = [1,0,0,1,0,0,1,1,1,0,0,0,0,0,0]
Output: 18880
```
**Example 5**:
```
Input: head = [0,0]
Output: 0
```
**Constraints**:
- The Linked List is not empty.
- Number of nodes will not exceed `30`.
- Each node's value is either `0` or `1`.
## 题目大意
给你一个单链表的引用结点 head。链表中每个结点的值不是 0 就是 1。已知此链表是一个整数数字的二进制表示形式。请你返回该链表所表示数字的 十进制值 。
提示:
- 链表不为空。
- 链表的结点总数不超过 30。
- 每个结点的值不是 0 就是 1。
## 解题思路
- 给出一个链表,链表从头到尾表示的数是一个整数的二进制形式,要求输出这个整数的十进制。
- 简单题,从头到尾遍历一次链表,边遍历边累加二进制位。
## 代码
```go
func getDecimalValue(head *ListNode) int {
sum := 0
for head != nil {
sum = sum*2 + head.Val
head = head.Next
}
return sum
}
```

View File

@@ -0,0 +1,11 @@
package leetcode
import "strconv"
func findNumbers(nums []int) int {
res := 0
for _, n := range nums {
res += 1 - len(strconv.Itoa(n))%2
}
return res
}

View File

@@ -0,0 +1,47 @@
package leetcode
import (
"fmt"
"testing"
)
type question1295 struct {
para1295
ans1295
}
// para 是参数
// one 代表第一个参数
type para1295 struct {
one []int
}
// ans 是答案
// one 代表第一个答案
type ans1295 struct {
one int
}
func Test_Problem1295(t *testing.T) {
qs := []question1295{
question1295{
para1295{[]int{12, 345, 2, 6, 7896}},
ans1295{2},
},
question1295{
para1295{[]int{555, 901, 482, 1771}},
ans1295{1},
},
}
fmt.Printf("------------------------Leetcode Problem 1295------------------------\n")
for _, q := range qs {
_, p := q.ans1295, q.para1295
fmt.Printf("【input】:%v 【output】:%v\n", p, findNumbers(p.one))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,62 @@
# 1295. Find Numbers with Even Number of Digits
## 题目
Given an array `nums` of integers, return how many of them contain an **even number** of digits.
**Example 1**:
```
Input: nums = [12,345,2,6,7896]
Output: 2
Explanation:
12 contains 2 digits (even number of digits).
345 contains 3 digits (odd number of digits).
2 contains 1 digit (odd number of digits).
6 contains 1 digit (odd number of digits).
7896 contains 4 digits (even number of digits).
Therefore only 12 and 7896 contain an even number of digits.
```
**Example 2**:
```
Input: nums = [555,901,482,1771]
Output: 1
Explanation:
Only 1771 contains an even number of digits.
```
**Constraints**:
- `1 <= nums.length <= 500`
- `1 <= nums[i] <= 10^5`
## 题目大意
给你一个整数数组 nums,请你返回其中位数为 偶数 的数字的个数。
提示:
- 1 <= nums.length <= 500
- 1 <= nums[i] <= 10^5
## 解题思路
- 给你一个整数数组,要求输出位数为偶数的数字的个数。
- 简单题,把每个数字转换为字符串判断长度是否是偶数即可。
## 代码
```go
func findNumbers(nums []int) int {
res := 0
for _, n := range nums {
res += 1 - len(strconv.Itoa(n))%2
}
return res
}
```

View File

@@ -0,0 +1,18 @@
package leetcode
func replaceElements(arr []int) []int {
j, temp := -1, 0
for i := len(arr) - 1; i >= 0; i-- {
temp = arr[i]
arr[i] = j
j = max(j, temp)
}
return arr
}
func max(a int, b int) int {
if a > b {
return a
}
return b
}

View File

@@ -0,0 +1,42 @@
package leetcode
import (
"fmt"
"testing"
)
type question1299 struct {
para1299
ans1299
}
// para 是参数
// one 代表第一个参数
type para1299 struct {
one []int
}
// ans 是答案
// one 代表第一个答案
type ans1299 struct {
one []int
}
func Test_Problem1299(t *testing.T) {
qs := []question1299{
question1299{
para1299{[]int{17, 18, 5, 4, 6, 1}},
ans1299{[]int{18, 6, 6, 6, 1, -1}},
},
}
fmt.Printf("------------------------Leetcode Problem 1299------------------------\n")
for _, q := range qs {
_, p := q.ans1299, q.para1299
fmt.Printf("【input】:%v 【output】:%v\n", p, replaceElements(p.one))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,50 @@
# 1299. Replace Elements with Greatest Element on Right Side
## 题目
Given an array `arr`, replace every element in that array with the greatest element among the elements to its right, and replace the last element with `-1`.
After doing so, return the array.
**Example 1**:
```
Input: arr = [17,18,5,4,6,1]
Output: [18,6,6,6,1,-1]
```
**Constraints**:
- `1 <= arr.length <= 10^4`
- `1 <= arr[i] <= 10^5`
## 题目大意
给你一个数组 arr ,请你将每个元素用它右边最大的元素替换,如果是最后一个元素,用 -1 替换。完成所有替换操作后,请你返回这个数组。
提示:
- 1 <= arr.length <= 10^4
- 1 <= arr[i] <= 10^5
## 解题思路
- 给出一个数组,要求把所有元素都替换成自己右边最大的元素,最后一位补上 -1 。最后输出变化以后的数组。
- 简单题,按照题意操作即可。
## 代码
```go
func replaceElements(arr []int) []int {
j, temp := -1, 0
for i := len(arr) - 1; i >= 0; i-- {
temp = arr[i]
arr[i] = j
j = max(j, temp)
}
return arr
}
```

View File

@@ -0,0 +1,34 @@
package leetcode
func findBestValue(arr []int, target int) int {
low, high := 0, 100000
for low < high {
mid := low + (high-low)>>1
if calculateSum(arr, mid) < target {
low = mid + 1
} else {
high = mid
}
}
// 比较阈值线分别定在 left - 1 和 left 的时候与 target 的接近程度
sum1, sum2 := calculateSum(arr, low-1), calculateSum(arr, low)
if target-sum1 <= sum2-target {
return low - 1
}
return low
}
func calculateSum(arr []int, mid int) int {
sum := 0
for _, num := range arr {
sum += min(num, mid)
}
return sum
}
func min(a int, b int) int {
if a > b {
return b
}
return a
}

View File

@@ -0,0 +1,53 @@
package leetcode
import (
"fmt"
"testing"
)
type question1300 struct {
para1300
ans1300
}
// para 是参数
// one 代表第一个参数
type para1300 struct {
arr []int
target int
}
// ans 是答案
// one 代表第一个答案
type ans1300 struct {
one int
}
func Test_Problem1300(t *testing.T) {
qs := []question1300{
question1300{
para1300{[]int{4, 9, 3}, 10},
ans1300{3},
},
question1300{
para1300{[]int{2, 3, 5}, 10},
ans1300{5},
},
question1300{
para1300{[]int{60864, 25176, 27249, 21296, 20204}, 56803},
ans1300{11361},
},
}
fmt.Printf("------------------------Leetcode Problem 1300------------------------\n")
for _, q := range qs {
_, p := q.ans1300, q.para1300
fmt.Printf("【input】:%v 【output】:%v\n", p, findBestValue(p.arr, p.target))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,84 @@
# 1300. Sum of Mutated Array Closest to Target
## 题目
Given an integer array `arr` and a target value `target`, return the integer `value` such that when we change all the integers larger than `value` in the given array to be equal to `value`, the sum of the array gets as close as possible (in absolute difference) to `target`.
In case of a tie, return the minimum such integer.
Notice that the answer is not neccesarilly a number from `arr`.
**Example 1**:
```
Input: arr = [4,9,3], target = 10
Output: 3
Explanation: When using 3 arr converts to [3, 3, 3] which sums 9 and that's the optimal answer.
```
**Example 2**:
```
Input: arr = [2,3,5], target = 10
Output: 5
```
**Example 3**:
```
Input: arr = [60864,25176,27249,21296,20204], target = 56803
Output: 11361
```
**Constraints**:
- `1 <= arr.length <= 10^4`
- `1 <= arr[i], target <= 10^5`
## 题目大意
给你一个整数数组 arr 和一个目标值 target ,请你返回一个整数 value ,使得将数组中所有大于 value 的值变成 value 后,数组的和最接近  target (最接近表示两者之差的绝对值最小)。如果有多种使得和最接近 target 的方案,请你返回这些整数中的最小值。请注意,答案不一定是 arr 中的数字。
提示:
- 1 <= arr.length <= 10^4
- 1 <= arr[i], target <= 10^5
## 解题思路
- 给出一个数组 arr 和 target。能否找到一个 value 值,使得将数组中所有大于 value 的值变成 value 后,数组的和最接近 target。如果有多种方法,输出 value 值最小的。
- 这一题可以用二分搜索来求解。最后输出的唯一解有 2 个限制条件,一个是变化后的数组和最接近 target 。另一个是输出的 value 是所有可能方法中最小值。二分搜索最终的 value 值。mid 就是尝试的 value 值,每选择一次 mid,就算一次总和,和 target 比较。由于数组里面每个数和 mid 差距各不相同,所以每次调整 mid 有可能出现 mid 选小了以后,距离 target 反而更大了;mid 选大了以后,距离 target 反而更小了。这里的解决办法是,把 value 上下方可能的值都拿出来比较一下。
## 代码
```go
func findBestValue(arr []int, target int) int {
low, high := 0, 100000
for low < high {
mid := low + (high-low)>>1
if calculateSum(arr, mid) < target {
low = mid + 1
} else {
high = mid
}
}
// 比较阈值线分别定在 left - 1 和 left 的时候与 target 的接近程度
sum1, sum2 := calculateSum(arr, low-1), calculateSum(arr, low)
if target-sum1 <= sum2-target {
return low - 1
}
return low
}
func calculateSum(arr []int, mid int) int {
sum := 0
for _, num := range arr {
sum += min(num, mid)
}
return sum
}
```

View File

@@ -0,0 +1,35 @@
package leetcode
import (
"github.com/halfrost/LeetCode-Go/structures"
)
// TreeNode define
type TreeNode = structures.TreeNode
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func deepestLeavesSum(root *TreeNode) int {
maxLevel, sum := 0, 0
dfsDeepestLeavesSum(root, 0, &maxLevel, &sum)
return sum
}
func dfsDeepestLeavesSum(root *TreeNode, level int, maxLevel, sum *int) {
if root == nil {
return
}
if level > *maxLevel {
*maxLevel, *sum = level, root.Val
} else if level == *maxLevel {
*sum += root.Val
}
dfsDeepestLeavesSum(root.Left, level+1, maxLevel, sum)
dfsDeepestLeavesSum(root.Right, level+1, maxLevel, sum)
}

View File

@@ -0,0 +1,49 @@
package leetcode
import (
"fmt"
"testing"
"github.com/halfrost/LeetCode-Go/structures"
)
type question1302 struct {
para1302
ans1302
}
// para 是参数
// one 代表第一个参数
type para1302 struct {
one []int
}
// ans 是答案
// one 代表第一个答案
type ans1302 struct {
one int
}
func Test_Problem1302(t *testing.T) {
qs := []question1302{
question1302{
para1302{[]int{1, 2, 3, 4, 5, structures.NULL, 6, 7, structures.NULL, structures.NULL, structures.NULL, structures.NULL, 8}},
ans1302{15},
},
question1302{
para1302{[]int{}},
ans1302{0},
},
}
fmt.Printf("------------------------Leetcode Problem 1302------------------------\n")
for _, q := range qs {
_, p := q.ans1302, q.para1302
fmt.Printf("【input】:%v 【output】:%v\n", p, deepestLeavesSum(structures.Ints2TreeNode(p.one)))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,57 @@
# 1302. Deepest Leaves Sum
## 题目
Given a binary tree, return the sum of values of its deepest leaves.
**Example 1**:
![https://assets.leetcode.com/uploads/2019/07/31/1483_ex1.png](https://assets.leetcode.com/uploads/2019/07/31/1483_ex1.png)
```
Input: root = [1,2,3,4,5,null,6,7,null,null,null,null,8]
Output: 15
```
**Constraints**:
- The number of nodes in the tree is between `1` and `10^4`.
- The value of nodes is between `1` and `100`.
## 题目大意
给你一棵二叉树,请你返回层数最深的叶子节点的和。
提示:
- 树中节点数目在 1 到 10^4 之间。
- 每个节点的值在 1 到 100 之间。
## 解题思路
- 给你一棵二叉树,请你返回层数最深的叶子节点的和。
- 这一题不难,DFS 遍历把最底层的叶子节点和都加起来即可。
## 代码
```go
func deepestLeavesSum(root *TreeNode) int {
maxLevel, sum := 0, 0
dfsDeepestLeavesSum(root, 0, &maxLevel, &sum)
return sum
}
func dfsDeepestLeavesSum(root *TreeNode, level int, maxLevel, sum *int) {
if root == nil {
return
}
if level > *maxLevel {
*maxLevel, *sum = level, root.Val
} else if level == *maxLevel {
*sum += root.Val
}
dfsDeepestLeavesSum(root.Left, level+1, maxLevel, sum)
dfsDeepestLeavesSum(root.Right, level+1, maxLevel, sum)
}
```

View File

@@ -0,0 +1,13 @@
package leetcode
func sumZero(n int) []int {
res, left, right, start := make([]int, n), 0, n-1, 1
for left < right {
res[left] = start
res[right] = -start
start++
left = left + 1
right = right - 1
}
return res
}

View File

@@ -0,0 +1,57 @@
package leetcode
import (
"fmt"
"testing"
)
type question1304 struct {
para1304
ans1304
}
// para 是参数
// one 代表第一个参数
type para1304 struct {
one int
}
// ans 是答案
// one 代表第一个答案
type ans1304 struct {
one []int
}
func Test_Problem1304(t *testing.T) {
qs := []question1304{
question1304{
para1304{5},
ans1304{[]int{-7, -1, 1, 3, 4}},
},
question1304{
para1304{0},
ans1304{[]int{}},
},
question1304{
para1304{3},
ans1304{[]int{-1, 0, 1}},
},
question1304{
para1304{1},
ans1304{[]int{0}},
},
}
fmt.Printf("------------------------Leetcode Problem 1304------------------------\n")
for _, q := range qs {
_, p := q.ans1304, q.para1304
fmt.Printf("【input】:%v 【output】:%v\n", p, sumZero(p.one))
}
fmt.Printf("\n\n\n")
}

Some files were not shown because too many files have changed in this diff Show More