Update solution 0617 & Add solution 0752

This commit is contained in:
YDZ
2021-06-27 08:47:05 +08:00
parent bc7c912aa9
commit d5c5284b1a
18 changed files with 553 additions and 33 deletions

View File

@ -20,14 +20,11 @@ func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode {
if root1 == nil {
return root2
}
if root2 == nil {
return root1
}
root1.Val += root2.Val
root1.Left = mergeTrees(root1.Left, root2.Left)
root1.Right = mergeTrees(root1.Right, root2.Right)
return root1
}

View File

@ -1,30 +1,80 @@
# [617. Merge Two Binary Trees](https://leetcode.com/problems/merge-two-binary-trees/)
## 题目
You are given two binary trees **root1** and **root2**.
You are given two binary trees `root1` and `root2`.
Imagine that when you put one of them to cover the other, some nodes of the two trees are overlapped while the others are not. You need to merge the two trees into a new binary tree. The merge rule is that if two nodes overlap, then sum node values up as the new value of the merged node. Otherwise, the NOT null node will be used as the node of the new tree.
Return the merged tree.
Return *the merged tree*.
**Note**: The merging process must start from the root nodes of both trees.
**Note:** The merging process must start from the root nodes of both trees.
**Example 1**:
**Example 1:**
![https://assets.leetcode.com/uploads/2021/02/05/merge.jpg](https://assets.leetcode.com/uploads/2021/02/05/merge.jpg)
```
Input: root1 = [1,3,2,5], root2 = [2,1,3,null,4,null,7]
Output: [3,4,5,5,4,null,7]
```
**Example 2**:
**Example 2:**
```
Input: root1 = [1], root2 = [1,2]
Output: [2,2]
```
**Constraints**:
**Constraints:**
1. The number of nodes in both trees is in the range [0, 2000].
2. -104 <= Node.val <= 104
- The number of nodes in both trees is in the range `[0, 2000]`.
- `104 <= Node.val <= 104`
## 题目大意
给定两个二叉树想象当你将它们中的一个覆盖到另一个上时两个二叉树的一些节点便会重叠。你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠那么将他们的值相加作为节点合并后的新值否则不为 NULL 的节点将直接作为新二叉树的节点。
## 解题思路
- 简单题。采用深搜的思路,分别从根节点开始同时遍历两个二叉树,并将对应的节点进行合并。两个二叉树的对应节点可能存在以下三种情况:
- 如果两个二叉树的对应节点都为空,则合并后的二叉树的对应节点也为空;
- 如果两个二叉树的对应节点只有一个为空,则合并后的二叉树的对应节点为其中的非空节点;
- 如果两个二叉树的对应节点都不为空,则合并后的二叉树的对应节点的值为两个二叉树的对应节点的值之和,此时需要显性合并两个节点。
- 对一个节点进行合并之后,还要对该节点的左右子树分别进行合并。用递归实现即可。
## 代码
```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 mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode {
if root1 == nil {
return root2
}
if root2 == nil {
return root1
}
root1.Val += root2.Val
root1.Left = mergeTrees(root1.Left, root2.Left)
root1.Right = mergeTrees(root1.Right, root2.Right)
return root1
}
```

View File

@ -0,0 +1,57 @@
package leetcode
func openLock(deadends []string, target string) int {
if target == "0000" {
return 0
}
targetNum, visited := strToInt(target), make([]bool, 10000)
visited[0] = true
for _, deadend := range deadends {
num := strToInt(deadend)
if num == 0 {
return -1
}
visited[num] = true
}
depth, curDepth, nextDepth := 0, []int16{0}, make([]int16, 0)
var nextNum int16
for len(curDepth) > 0 {
nextDepth = nextDepth[0:0]
for _, curNum := range curDepth {
for incrementer := int16(1000); incrementer > 0; incrementer /= 10 {
digit := (curNum / incrementer) % 10
if digit == 9 {
nextNum = curNum - 9*incrementer
} else {
nextNum = curNum + incrementer
}
if nextNum == targetNum {
return depth + 1
}
if !visited[nextNum] {
visited[nextNum] = true
nextDepth = append(nextDepth, nextNum)
}
if digit == 0 {
nextNum = curNum + 9*incrementer
} else {
nextNum = curNum - incrementer
}
if nextNum == targetNum {
return depth + 1
}
if !visited[nextNum] {
visited[nextNum] = true
nextDepth = append(nextDepth, nextNum)
}
}
}
curDepth, nextDepth = nextDepth, curDepth
depth++
}
return -1
}
func strToInt(str string) int16 {
return int16(str[0]-'0')*1000 + int16(str[1]-'0')*100 + int16(str[2]-'0')*10 + int16(str[3]-'0')
}

View File

@ -0,0 +1,53 @@
package leetcode
import (
"fmt"
"testing"
)
type question752 struct {
para752
ans752
}
// para 是参数
// one 代表第一个参数
type para752 struct {
deadends []string
target string
}
// ans 是答案
// one 代表第一个答案
type ans752 struct {
one int
}
func Test_Problem752(t *testing.T) {
qs := []question752{
{
para752{[]string{"0201", "0101", "0102", "1212", "2002"}, "0202"},
ans752{6},
},
{
para752{[]string{"8888"}, "0009"},
ans752{1},
},
{
para752{[]string{"8887", "8889", "8878", "8898", "8788", "8988", "7888", "9888"}, "8888"},
ans752{-1},
},
}
fmt.Printf("------------------------Leetcode Problem 752------------------------\n")
for _, q := range qs {
_, p := q.ans752, q.para752
fmt.Printf("【input】:%v 【output】:%v\n", p, openLock(p.deadends, p.target))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,131 @@
# [752. Open the Lock](https://leetcode.com/problems/open-the-lock/)
## 题目
You have a lock in front of you with 4 circular wheels. Each wheel has 10 slots: `'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'`. The wheels can rotate freely and wrap around: for example we can turn `'9'` to be `'0'`, or `'0'` to be `'9'`. Each move consists of turning one wheel one slot.
The lock initially starts at `'0000'`, a string representing the state of the 4 wheels.
You are given a list of `deadends` dead ends, meaning if the lock displays any of these codes, the wheels of the lock will stop turning and you will be unable to open it.
Given a `target` representing the value of the wheels that will unlock the lock, return the minimum total number of turns required to open the lock, or -1 if it is impossible.
**Example 1:**
```
Input: deadends = ["0201","0101","0102","1212","2002"], target = "0202"
Output: 6
Explanation:
A sequence of valid moves would be "0000" -> "1000" -> "1100" -> "1200" -> "1201" -> "1202" -> "0202".
Note that a sequence like "0000" -> "0001" -> "0002" -> "0102" -> "0202" would be invalid,
because the wheels of the lock become stuck after the display becomes the dead end "0102".
```
**Example 2:**
```
Input: deadends = ["8888"], target = "0009"
Output: 1
Explanation:
We can turn the last wheel in reverse to move from "0000" -> "0009".
```
**Example 3:**
```
Input: deadends = ["8887","8889","8878","8898","8788","8988","7888","9888"], target = "8888"
Output: -1
Explanation:
We can't reach the target without getting stuck.
```
**Example 4:**
```
Input: deadends = ["0000"], target = "8888"
Output: -1
```
**Constraints:**
- `1 <= deadends.length <= 500`
- `deadends[i].length == 4`
- `target.length == 4`
- target **will not be** in the list `deadends`.
- `target` and `deadends[i]` consist of digits only.
## 题目大意
你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' 。每个拨轮可以自由旋转:例如把 '9' 变为 '0''0' 变为 '9' 。每次旋转都只能旋转一个拨轮的一位数字。锁的初始数字为 '0000' ,一个代表四个拨轮的数字的字符串。列表 deadends 包含了一组死亡数字,一旦拨轮的数字和列表里的任何一个元素相同,这个锁将会被永久锁定,无法再被旋转。字符串 target 代表可以解锁的数字,你需要给出解锁需要的最小旋转次数,如果无论如何不能解锁,返回 -1 。
## 解题思路
- 此题可以转化为从起始点到终点的最短路径。采用广度优先搜索。每次广搜枚举转动一次数字的状态,并且用 visited 记录是否被搜索过,如果没有被搜索过,便加入队列,下一轮继续搜索。如果搜索到了 target便返回对应的旋转次数。如果搜索完成后仍没有搜索到 target说明无法解锁返回 -1。特殊情况如果 target 就是初始数字 0000那么直接返回答案 0。
- 在广搜之前,先将 deadends 放入 map 中,搜索中判断是否搜到了 deadends。如果初始数字 0000 出现在 deadends 中,可以直接返回答案 1。
## 代码
```go
package leetcode
func openLock(deadends []string, target string) int {
if target == "0000" {
return 0
}
targetNum, visited := strToInt(target), make([]bool, 10000)
visited[0] = true
for _, deadend := range deadends {
num := strToInt(deadend)
if num == 0 {
return -1
}
visited[num] = true
}
depth, curDepth, nextDepth := 0, []int16{0}, make([]int16, 0)
var nextNum int16
for len(curDepth) > 0 {
nextDepth = nextDepth[0:0]
for _, curNum := range curDepth {
for incrementer := int16(1000); incrementer > 0; incrementer /= 10 {
digit := (curNum / incrementer) % 10
if digit == 9 {
nextNum = curNum - 9*incrementer
} else {
nextNum = curNum + incrementer
}
if nextNum == targetNum {
return depth + 1
}
if !visited[nextNum] {
visited[nextNum] = true
nextDepth = append(nextDepth, nextNum)
}
if digit == 0 {
nextNum = curNum + 9*incrementer
} else {
nextNum = curNum - incrementer
}
if nextNum == targetNum {
return depth + 1
}
if !visited[nextNum] {
visited[nextNum] = true
nextDepth = append(nextDepth, nextNum)
}
}
}
curDepth, nextDepth = nextDepth, curDepth
depth++
}
return -1
}
func strToInt(str string) int16 {
return int16(str[0]-'0')*1000 + int16(str[1]-'0')*100 + int16(str[2]-'0')*10 + int16(str[3]-'0')
}
```