mirror of
https://github.com/halfrost/LeetCode-Go.git
synced 2025-07-05 00:25:22 +08:00
Add solution 1293、2096
This commit is contained in:
@ -0,0 +1,71 @@
|
||||
package leetcode
|
||||
|
||||
var dir = [][]int{
|
||||
{-1, 0},
|
||||
{0, 1},
|
||||
{1, 0},
|
||||
{0, -1},
|
||||
}
|
||||
|
||||
type pos struct {
|
||||
x, y int
|
||||
obstacle int
|
||||
step int
|
||||
}
|
||||
|
||||
func shortestPath(grid [][]int, k int) int {
|
||||
queue, m, n := []pos{}, len(grid), len(grid[0])
|
||||
visitor := make([][][]int, m)
|
||||
if len(grid) == 1 && len(grid[0]) == 1 {
|
||||
return 0
|
||||
}
|
||||
for i := 0; i < m; i++ {
|
||||
visitor[i] = make([][]int, n)
|
||||
for j := 0; j < n; j++ {
|
||||
visitor[i][j] = make([]int, k+1)
|
||||
}
|
||||
}
|
||||
visitor[0][0][0] = 1
|
||||
queue = append(queue, pos{x: 0, y: 0, obstacle: 0, step: 0})
|
||||
for len(queue) > 0 {
|
||||
size := len(queue)
|
||||
for size > 0 {
|
||||
size--
|
||||
node := queue[0]
|
||||
queue = queue[1:]
|
||||
for i := 0; i < len(dir); i++ {
|
||||
newX := node.x + dir[i][0]
|
||||
newY := node.y + dir[i][1]
|
||||
if newX == m-1 && newY == n-1 {
|
||||
if node.obstacle != 0 {
|
||||
if node.obstacle <= k {
|
||||
return node.step + 1
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
return node.step + 1
|
||||
}
|
||||
if isInBoard(grid, newX, newY) {
|
||||
if grid[newX][newY] == 1 {
|
||||
if node.obstacle+1 <= k && visitor[newX][newY][node.obstacle+1] != 1 {
|
||||
queue = append(queue, pos{x: newX, y: newY, obstacle: node.obstacle + 1, step: node.step + 1})
|
||||
visitor[newX][newY][node.obstacle+1] = 1
|
||||
}
|
||||
} else {
|
||||
if node.obstacle <= k && visitor[newX][newY][node.obstacle] != 1 {
|
||||
queue = append(queue, pos{x: newX, y: newY, obstacle: node.obstacle, step: node.step + 1})
|
||||
visitor[newX][newY][node.obstacle] = 1
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func isInBoard(board [][]int, x, y int) bool {
|
||||
return x >= 0 && x < len(board) && y >= 0 && y < len(board[0])
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question1293 struct {
|
||||
para1293
|
||||
ans1293
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para1293 struct {
|
||||
grid [][]int
|
||||
k int
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans1293 struct {
|
||||
one int
|
||||
}
|
||||
|
||||
func Test_Problem1293(t *testing.T) {
|
||||
|
||||
qs := []question1293{
|
||||
|
||||
{
|
||||
para1293{[][]int{
|
||||
{0, 0, 0},
|
||||
}, 1},
|
||||
ans1293{2},
|
||||
},
|
||||
|
||||
{
|
||||
para1293{[][]int{
|
||||
{0, 1, 1}, {0, 1, 1}, {0, 0, 0}, {0, 1, 0}, {0, 1, 0},
|
||||
}, 2},
|
||||
ans1293{6},
|
||||
},
|
||||
|
||||
{
|
||||
para1293{[][]int{
|
||||
{0, 0, 0}, {1, 1, 0}, {0, 0, 0}, {0, 1, 1}, {0, 0, 0},
|
||||
}, 1},
|
||||
ans1293{6},
|
||||
},
|
||||
|
||||
{
|
||||
para1293{[][]int{
|
||||
{0, 1, 1}, {1, 1, 1}, {1, 0, 0},
|
||||
}, 1},
|
||||
ans1293{-1},
|
||||
},
|
||||
|
||||
{
|
||||
para1293{[][]int{
|
||||
{0},
|
||||
}, 1},
|
||||
ans1293{0},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 1293------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans1293, q.para1293
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, shortestPath(p.grid, p.k))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
# [1293. Shortest Path in a Grid with Obstacles Elimination](https://leetcode.com/problems/shortest-path-in-a-grid-with-obstacles-elimination/)
|
||||
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
You are given an m x n integer matrix grid where each cell is either 0 (empty) or 1 (obstacle). You can move up, down, left, or right from and to an empty cell in one step.
|
||||
|
||||
Return the minimum number of steps to walk from the upper left corner (0, 0) to the lower right corner (m - 1, n - 1) given that you can eliminate at most k obstacles. If it is not possible to find such walk return -1.
|
||||
|
||||
|
||||
|
||||
Example 1:
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
```
|
||||
Input: grid = [[0,0,0],[1,1,0],[0,0,0],[0,1,1],[0,0,0]], k = 1
|
||||
Output: 6
|
||||
Explanation:
|
||||
The shortest path without eliminating any obstacle is 10.
|
||||
The shortest path with one obstacle elimination at position (3,2) is 6. Such path is (0,0) -> (0,1) -> (0,2) -> (1,2) -> (2,2) -> (3,2) -> (4,2).
|
||||
```
|
||||
|
||||
Example 2:
|
||||
|
||||

|
||||
|
||||
```
|
||||
Input: grid = [[0,1,1],[1,1,1],[1,0,0]], k = 1
|
||||
Output: -1
|
||||
Explanation: We need to eliminate at least two obstacles to find such a walk.
|
||||
```
|
||||
|
||||
Constraints:
|
||||
|
||||
- m == grid.length
|
||||
- n == grid[i].length
|
||||
- 1 <= m, n <= 40
|
||||
- 1 <= k <= m * n
|
||||
- grid[i][j] is either 0 or 1.
|
||||
- grid[0][0] == grid[m - 1][n - 1] == 0
|
||||
|
||||
|
||||
|
||||
## 题目大意
|
||||
|
||||
给你一个 m * n 的网格,其中每个单元格不是 0(空)就是 1(障碍物)。每一步,您都可以在空白单元格中上、下、左、右移动。
|
||||
|
||||
如果您 最多 可以消除 k 个障碍物,请找出从左上角 (0, 0) 到右下角 (m-1, n-1) 的最短路径,并返回通过该路径所需的步数。如果找不到这样的路径,则返回 -1 。
|
||||
|
||||
|
||||
## 解题思路
|
||||
|
||||
使用 BFS 遍历棋盘。这题比普通可达性问题多了一个障碍物的限制。这个也不难。每个点往周边四个方向扩展的时候,如果遇到障碍物,先算上这个障碍物,障碍物累积总个数小于 K 的时候,从障碍物的这个格子继续开始遍历。如果没有遇到障碍物,判断当前累积障碍物个数是否已经小于 K 个,如果小于 K 便继续遍历。如果大于 K,便终止此轮遍历。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
var dir = [][]int{
|
||||
{-1, 0},
|
||||
{0, 1},
|
||||
{1, 0},
|
||||
{0, -1},
|
||||
}
|
||||
|
||||
type pos struct {
|
||||
x, y int
|
||||
obstacle int
|
||||
step int
|
||||
}
|
||||
|
||||
func shortestPath(grid [][]int, k int) int {
|
||||
queue, m, n := []pos{}, len(grid), len(grid[0])
|
||||
visitor := make([][][]int, m)
|
||||
if len(grid) == 1 && len(grid[0]) == 1 {
|
||||
return 0
|
||||
}
|
||||
for i := 0; i < m; i++ {
|
||||
visitor[i] = make([][]int, n)
|
||||
for j := 0; j < n; j++ {
|
||||
visitor[i][j] = make([]int, k+1)
|
||||
}
|
||||
}
|
||||
visitor[0][0][0] = 1
|
||||
queue = append(queue, pos{x: 0, y: 0, obstacle: 0, step: 0})
|
||||
for len(queue) > 0 {
|
||||
size := len(queue)
|
||||
for size > 0 {
|
||||
size--
|
||||
node := queue[0]
|
||||
queue = queue[1:]
|
||||
for i := 0; i < len(dir); i++ {
|
||||
newX := node.x + dir[i][0]
|
||||
newY := node.y + dir[i][1]
|
||||
if newX == m-1 && newY == n-1 {
|
||||
if node.obstacle != 0 {
|
||||
if node.obstacle <= k {
|
||||
return node.step + 1
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
return node.step + 1
|
||||
}
|
||||
if isInBoard(grid, newX, newY) {
|
||||
if grid[newX][newY] == 1 {
|
||||
if node.obstacle+1 <= k && visitor[newX][newY][node.obstacle+1] != 1 {
|
||||
queue = append(queue, pos{x: newX, y: newY, obstacle: node.obstacle + 1, step: node.step + 1})
|
||||
visitor[newX][newY][node.obstacle+1] = 1
|
||||
}
|
||||
} else {
|
||||
if node.obstacle <= k && visitor[newX][newY][node.obstacle] != 1 {
|
||||
queue = append(queue, pos{x: newX, y: newY, obstacle: node.obstacle, step: node.step + 1})
|
||||
visitor[newX][newY][node.obstacle] = 1
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func isInBoard(board [][]int, x, y int) bool {
|
||||
return x >= 0 && x < len(board) && y >= 0 && y < len(board[0])
|
||||
}
|
||||
```
|
@ -0,0 +1,77 @@
|
||||
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 getDirections(root *TreeNode, startValue int, destValue int) string {
|
||||
sPath, dPath := make([]byte, 0), make([]byte, 0)
|
||||
findPath(root, startValue, &sPath)
|
||||
findPath(root, destValue, &dPath)
|
||||
size, i := min(len(sPath), len(dPath)), 0
|
||||
for i < size {
|
||||
if sPath[len(sPath)-1-i] == dPath[len(dPath)-1-i] {
|
||||
i++
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
sPath = sPath[:len(sPath)-i]
|
||||
replace(sPath)
|
||||
dPath = dPath[:len(dPath)-i]
|
||||
reverse(dPath)
|
||||
sPath = append(sPath, dPath...)
|
||||
return string(sPath)
|
||||
}
|
||||
|
||||
func findPath(root *TreeNode, value int, path *[]byte) bool {
|
||||
if root.Val == value {
|
||||
return true
|
||||
}
|
||||
|
||||
if root.Left != nil && findPath(root.Left, value, path) {
|
||||
*path = append(*path, 'L')
|
||||
return true
|
||||
}
|
||||
|
||||
if root.Right != nil && findPath(root.Right, value, path) {
|
||||
*path = append(*path, 'R')
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func reverse(path []byte) {
|
||||
left, right := 0, len(path)-1
|
||||
for left < right {
|
||||
path[left], path[right] = path[right], path[left]
|
||||
left++
|
||||
right--
|
||||
}
|
||||
}
|
||||
|
||||
func replace(path []byte) {
|
||||
for i := 0; i < len(path); i++ {
|
||||
path[i] = 'U'
|
||||
}
|
||||
}
|
||||
|
||||
func min(i, j int) int {
|
||||
if i < j {
|
||||
return i
|
||||
}
|
||||
return j
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/halfrost/LeetCode-Go/structures"
|
||||
)
|
||||
|
||||
type question2096 struct {
|
||||
para2096
|
||||
ans2096
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para2096 struct {
|
||||
one []int
|
||||
startValue int
|
||||
destValue int
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans2096 struct {
|
||||
one string
|
||||
}
|
||||
|
||||
func Test_Problem2096(t *testing.T) {
|
||||
|
||||
qs := []question2096{
|
||||
|
||||
{
|
||||
para2096{[]int{5, 1, 2, 3, structures.NULL, 6, 4}, 3, 6},
|
||||
ans2096{"UURL"},
|
||||
},
|
||||
|
||||
{
|
||||
para2096{[]int{2, 1}, 2, 1},
|
||||
ans2096{"L"},
|
||||
},
|
||||
|
||||
{
|
||||
para2096{[]int{1, 2}, 2, 1},
|
||||
ans2096{"U"},
|
||||
},
|
||||
|
||||
{
|
||||
para2096{[]int{3, 1, 2}, 2, 1},
|
||||
ans2096{"UL"},
|
||||
},
|
||||
|
||||
{
|
||||
para2096{[]int{7, 8, 3, 1, structures.NULL, 4, 5, 6, structures.NULL, structures.NULL, structures.NULL, structures.NULL, structures.NULL, structures.NULL, 2}, 7, 5},
|
||||
ans2096{"RR"},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 2096------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans2096, q.para2096
|
||||
fmt.Printf("【input】:%v ", p)
|
||||
root := structures.Ints2TreeNode(p.one)
|
||||
fmt.Printf("【output】:%v \n", getDirections(root, p.startValue, p.destValue))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
@ -0,0 +1,145 @@
|
||||
# [2096. Step-By-Step Directions From a Binary Tree Node to Another](https://leetcode.com/problems/step-by-step-directions-from-a-binary-tree-node-to-another/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
You are given the `root` of a **binary tree** with `n` nodes. Each node is uniquely assigned a value from `1` to `n`. You are also given an integer `startValue` representing the value of the start node `s`, and a different integer `destValue` representing the value of the destination node `t`.
|
||||
|
||||
Find the **shortest path** starting from node `s` and ending at node `t`. Generate step-by-step directions of such path as a string consisting of only the **uppercase** letters `'L'`, `'R'`, and `'U'`. Each letter indicates a specific direction:
|
||||
|
||||
- `'L'` means to go from a node to its **left child** node.
|
||||
- `'R'` means to go from a node to its **right child** node.
|
||||
- `'U'` means to go from a node to its **parent** node.
|
||||
|
||||
Return *the step-by-step directions of the **shortest path** from node* `s` *to node* `t`.
|
||||
|
||||
**Example 1:**
|
||||
|
||||

|
||||
|
||||
```
|
||||
Input: root = [5,1,2,3,null,6,4], startValue = 3, destValue = 6
|
||||
Output: "UURL"
|
||||
Explanation: The shortest path is: 3 → 1 → 5 → 2 → 6.
|
||||
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||

|
||||
|
||||
```
|
||||
Input: root = [2,1], startValue = 2, destValue = 1
|
||||
Output: "L"
|
||||
Explanation: The shortest path is: 2 → 1.
|
||||
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- The number of nodes in the tree is `n`.
|
||||
- `2 <= n <= 105`
|
||||
- `1 <= Node.val <= n`
|
||||
- All the values in the tree are **unique**.
|
||||
- `1 <= startValue, destValue <= n`
|
||||
- `startValue != destValue`
|
||||
|
||||
## 题目大意
|
||||
|
||||
给你一棵 二叉树 的根节点 root ,这棵二叉树总共有 n 个节点。每个节点的值为 1 到 n 中的一个整数,且互不相同。给你一个整数 startValue ,表示起点节点 s 的值,和另一个不同的整数 destValue ,表示终点节点 t 的值。
|
||||
|
||||
请找到从节点 s 到节点 t 的 最短路径 ,并以字符串的形式返回每一步的方向。每一步用 大写 字母 'L' ,'R' 和 'U' 分别表示一种方向:
|
||||
|
||||
- 'L' 表示从一个节点前往它的 左孩子 节点。
|
||||
- 'R' 表示从一个节点前往它的 右孩子 节点。
|
||||
- 'U' 表示从一个节点前往它的 父 节点。
|
||||
|
||||
请你返回从 s 到 t 最短路径 每一步的方向。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 二叉树中一个节点到另一个节点的最短路径一定可以分为两个部分(可能为空):从起点节点向上到两个节点的**最近公共祖先**,再从最近公共祖先向下到达终点节点。
|
||||
- 首先需要找到起点 s 与公共祖先的节点之间的 path1,公共祖先节点与终点 t 的 path2。再删掉 2 个 path 的公共前缀。如果起点 s 和终点 t 在不同的分支上,不存在公共前缀。如果他们在相同的分支上,那么最终答案要去掉这个公共前缀。
|
||||
- 删除掉公共前缀以后,需要再整理一下最终答案的输出格式。由于题目要求,起点到公共祖先节点需要输出 U,所以把这段 path1 全部改成 U,然后再拼接上 path2 字符串,即可得到的字符串即为待求 ss 到 tt 每一步的最短路径。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
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 getDirections(root *TreeNode, startValue int, destValue int) string {
|
||||
sPath, dPath := make([]byte, 0), make([]byte, 0)
|
||||
findPath(root, startValue, &sPath)
|
||||
findPath(root, destValue, &dPath)
|
||||
size, i := min(len(sPath), len(dPath)), 0
|
||||
for i < size {
|
||||
if sPath[len(sPath)-1-i] == dPath[len(dPath)-1-i] {
|
||||
i++
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
sPath = sPath[:len(sPath)-i]
|
||||
replace(sPath)
|
||||
dPath = dPath[:len(dPath)-i]
|
||||
reverse(dPath)
|
||||
sPath = append(sPath, dPath...)
|
||||
return string(sPath)
|
||||
}
|
||||
|
||||
func findPath(root *TreeNode, value int, path *[]byte) bool {
|
||||
if root.Val == value {
|
||||
return true
|
||||
}
|
||||
|
||||
if root.Left != nil && findPath(root.Left, value, path) {
|
||||
*path = append(*path, 'L')
|
||||
return true
|
||||
}
|
||||
|
||||
if root.Right != nil && findPath(root.Right, value, path) {
|
||||
*path = append(*path, 'R')
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func reverse(path []byte) {
|
||||
left, right := 0, len(path)-1
|
||||
for left < right {
|
||||
path[left], path[right] = path[right], path[left]
|
||||
left++
|
||||
right--
|
||||
}
|
||||
}
|
||||
|
||||
func replace(path []byte) {
|
||||
for i := 0; i < len(path); i++ {
|
||||
path[i] = 'U'
|
||||
}
|
||||
}
|
||||
|
||||
func min(i, j int) int {
|
||||
if i < j {
|
||||
return i
|
||||
}
|
||||
return j
|
||||
}
|
||||
```
|
Reference in New Issue
Block a user