Go小白,希望一边刷LeetCode算法顺便掌握Go基本语法,在这里记录遇到的所有愚蠢问题。
105. 从前序与中序遍历序列构造二叉树
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
示例 1:
输入 : preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]
示例 2:
输入: preorder = [-1], inorder = [-1]
输出: [-1]
解答
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
import (
"fmt"
)
func buildTree(preorder []int, inorder []int) *TreeNode {
if len(preorder) == 0 {
return nil
}
root := new(TreeNode)
root.Val = preorder[0]
root.Left = nil
root.Right = nil
if len(preorder) == 1 {
// 只有一个节点,不需要继续递归
return root
} else {
// 找到root在inorder中的index
// var index = sort.SearchInts(inorder, preorder[0])
var index = slices.Index(inorder, preorder[0])
fmt.Print(index)
if index == len(inorder) {
fmt.Print("越界")
}
root.Left = buildTree(preorder[1: len(inorder[0:index]) + 1], inorder[:index])
root.Right = buildTree(preorder[len(inorder[0:index]) + 1:], inorder[index + 1:])
return root
}
}
遇到的问题1
被题目给出的实例误导了,例子里面给出的左节点的大小为1,就想当然地将递归方法里面的参数写成了
root.Left = buildTree(preorder[1: index + 1], inorder[:index])
root.Right = buildTree(preorder[index + 1:], inorder[index + 1:])
遇到的问题2
偷懒不想遍历查找preorder[0]在inorder中的下标,想用
var index = sort.SearchInts(inorder, preorder[0])
发现一直报错数组越界,后面把index打印出来发现是index就找错了。查找资料发现sort.SearchInts()用的是二分查找,也就是传入的数组必须是排好序的。 用slices.Index()或者手动循环查找替代即可。
103. 二叉树的锯齿形层序遍历
给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。
示例 1:
输入: root = [3,9,20,null,null,15,7]
输出: [[3],[20,9],[15,7]]
示例 2:
输入: root = [1]
输出: [[1]]
示例 3:
输入: root = []
输出: []
解答
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func zigzagLevelOrder(root *TreeNode) [][]int {
if root == nil{
return [][]int{}
}
parentNum, ChildNum := 1, 0
index := 0
quene := []*TreeNode{root}
tmp := []int{}
output := [][]int{[]int{root.Val}}
flag := false
for len(quene) > 0 {
if quene[index].Left != nil {
quene = append(quene, quene[index].Left)
ChildNum += 1
tmp = append(tmp, quene[index].Left.Val)
}
if quene[index].Right != nil {
quene = append(quene, quene[index].Right)
ChildNum += 1
tmp = append(tmp, quene[index].Right.Val)
}
if index == parentNum -1 {
if ChildNum == 0 {break}
if flag {
output = append(output, tmp)
} else {
rev := []int{}
for _, n := range tmp {
rev = append([]int{n}, rev...)
}
output = append(output, rev)
}
flag = !flag
tmp = []int{}
parentNum = ChildNum
ChildNum = 0
quene = quene[index+1:]
index = 0
} else {
index += 1
}
}
return output
}
这道题其实就是层序遍历,只是在遍历的时候加上了方向的变化。官方题解有用到双向队列,但是我比较懒就直接把写的层序遍历拿过来改了。 我觉得值得记录的是go的reverse方法。
方法1:
在Go语言中,"..."(三个点)用于创建切片(slice)的变长参数。在这个代码片段中,"..."的作用是将数组中的每个元素追加到切片中。具体来说,... 将 array 中的每个元素作为单独的参数传递给 append 函数,以将其添加到 rev 切片的开头位置。
var rev []string
for _, n := range array {
rev = append([]string{n}, rev...)
}
方法2:
for i,j := 0, len(array)-1 ; i < j ; i, j = i+1, j-1 {
array[i],array[j] = array[j], array[i]
}
200. 岛屿数量
给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
示例 1:
输入: grid = [ ["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]
]
输出: 1
示例 2:
输入: grid = [ ["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
输出: 3
深度搜索的方法在这里不记录了,下面是广度搜索的实现。
错误1
// 广度搜索
func numIslands(grid [][]byte) int {
if grid == nil {
return 0
}
number := 0
type Point struct {
point1, point2 int
}
quene := []Point{{0, 0}}
for i := 0; i < len(grid); i++ {
for j := 0; j < len(grid[0]); j++ {
if grid[i][j] == '1' {
number += 1
// grid[i][j] = '0'
for len(quene) > 0 {
// 开始广度优先
point := quene[0]
r, c := point.point1, point.point2
quene = quene[1:]
var newPoint Point
if r - 1 >= 0 && grid[r-1][c] == '1' {
newPoint = Point{r-1, c}
quene = append(quene, newPoint)
grid[r-1][c] = '0'
}
if r + 1 < len(grid) && grid[r+1][c] == '1' {
newPoint = Point{r+1, c}
quene = append(quene, newPoint)
grid[r+1][c] = '0'
}
if c - 1 >= 0 && grid[r][c-1] == '1' {
newPoint = Point{r, c-1}
quene = append(quene, newPoint)
grid[r][c-1] = '0'
}
if c + 1 < len(grid[0]) && grid[r][c+1] == '1' {
newPoint = Point{r, c+1}
quene = append(quene, newPoint)
grid[r][c+1] = '0'
}
}
}
}
}
return number
}
把quene写在了循环的外面,这样的问题是除了[0][0]位置外的‘1’都不会被添加到quene中, 1)[0][0]位置的元素不一定是‘1’,因此不一定需要添加进来 2)后面遇到的其他的首次出现在岛屿中的‘1’元素失去了被添加进quene的机会 修改方法:
// 广度搜索
func numIslands(grid [][]byte) int {
if grid == nil {
return 0
}
number := 0
type Point struct {
point1, point2 int
}
for i := 0; i < len(grid); i++ {
for j := 0; j < len(grid[0]); j++ {
if grid[i][j] == '1' {
number += 1
// grid[i][j] = '0'
quene := []Point{{i, j}}
for len(quene) > 0 {
// 开始广度优先
point := quene[0]
r, c := point.point1, point.point2
quene = quene[1:]
var newPoint Point
if r - 1 >= 0 && grid[r-1][c] == '1' {
newPoint = Point{r-1, c}
quene = append(quene, newPoint)
grid[r-1][c] = '0'
}
if r + 1 < len(grid) && grid[r+1][c] == '1' {
newPoint = Point{r+1, c}
quene = append(quene, newPoint)
grid[r+1][c] = '0'
}
if c - 1 >= 0 && grid[r][c-1] == '1' {
newPoint = Point{r, c-1}
quene = append(quene, newPoint)
grid[r][c-1] = '0'
}
if c + 1 < len(grid[0]) && grid[r][c+1] == '1' {
newPoint = Point{r, c+1}
quene = append(quene, newPoint)
grid[r][c+1] = '0'
}
}
}
}
}
return number
}
值得记录的点: Go语言中没有预先实现好的tuple,如果要实现类似的功能需要自定义struct来完成:
type Point struct {
point1, point2 int
}
使用并查集的方法可以先学习一下并查集的概念,参考这篇帖子。