基础知识
队列是一种常用的数据结构,它最大的特点是“先入先出”,即先进入队列中的元素最先出来。这和我们日常生活中的队列一致,排在队列最前面的人优先得到服务。由于队列要保证“先入先出”的顺序,因此新的元素只能添加到队列的尾部,同时只能删除位于队列最前面的元素。
如果解决某个问题时数据的插入和删除操作满足“先入先出”的特点,那么可以考虑用队列来存储这些数据。 如滑动窗口,最近请求次数,二叉树广度优先遍历。
常见算法
一、在完全二叉树中添加节点
题目:在完全二叉树中,除最后一层之外其他层的节点都是满的(第n层有2n-1个节点)。最后一层的节点可能不满,该层所有的节点尽可能向左边靠拢。例如,图7.3中的4棵二叉树均为完全二叉树。实现数据结构CBTInserter有如下3种方法。
● 构造函数CBTInserter(TreeNode root),用一棵完全二叉树的根节点初始化该数据结构。
● 函数insert(int v)在完全二叉树中添加一个值为v的节点,并返回被插入节点的父节点。例如,在如图(a)所示的完全二叉树中添加一个值为7的节点之后,二叉树如图(b)所示,并返回节点3。在如图(b)所示的完全二叉树中添加一个值为8的节点之后,二叉树如图(c)所示,并返回节点4。在如图(c)所示的完全二叉树中添加节点9会得到如图7.3(d)所示的二叉树并返回节点4。
● 函数get_root()返回完全二叉树的根节点。
解题思路
Golang代码
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
type CBTInserter struct {
Root *TreeNode
ParentList []*TreeNode
}
func Constructor(root *TreeNode) CBTInserter {
list := make([]*TreeNode, 0)
parents := make([]*TreeNode, 0)
if root == nil {
return CBTInserter{
Root: root,
ParentList: parents,
}
}
list = append(list, root)
for len(list) > 0 {
node := list[0]
if node.Left != nil {
list = append(list, node.Left)
}
if node.Right != nil {
list = append(list, node.Right)
}
if node.Left == nil || node.Right == nil {
parents = append(parents, node)
}
list = list[1:]
}
return CBTInserter{
Root: root,
ParentList: parents,
}
}
func (this *CBTInserter) Insert(v int) int {
node := &TreeNode{Val: v}
parent := this.ParentList[0]
if parent.Left == nil {
parent.Left = node
}
if parent.Right == nil {
parent.Right = node
this.ParentList = this.ParentList[1:]
}
this.ParentList = append(this.ParentList, node)
return parent.Val
}
func (this *CBTInserter) Get_root() *TreeNode {
return this.Root
}
二、二叉树中每层的最大
题目:输入一棵二叉树,请找出二叉树中每层的最大值。
解题思路
- 使用队列做广度优先遍历
- 用双指针,一个在一层递减,一个在下一层增,直到队列结束
Golang代码
func largestValues(root *TreeNode) []int {
res := make([]int, 0)
if root == nil {
return res
}
var (
one int
two int
max = -1 << 31
)
list := make([]*TreeNode, 0)
list = append(list, root)
one = 1
for len(list) > 0 {
node := list[0]
list = list[1:]
one--
if node.Val > max {
max = node.Val
}
if node.Left != nil {
list = append(list, node.Left)
two++
}
if node.Right != nil {
list = append(list, node.Right)
two++
}
if one <= 0 {
one = two
two = 0
res = append(res, max)
max = -1 << 31
}
}
return res
}
三、二叉树最低层最左边的值
题目:如何在一棵二叉树中找出它最低层最左边节点的值?假设二叉树中最少有一个节点。
解题思路
- 使用队列做广度优先遍历
- 用双指针切片,一个在一层递减,一个在下一层增,直到队列结束,返回最后一个切片的第一个值。
Golang代码
func findBottomLeftValue(root *TreeNode) int {
res := make([]int, 0)
if root == nil {
return 0
}
var (
one = make([]int, 0)
two = make([]int, 0)
)
list := make([]*TreeNode, 0)
list = append(list, root)
one = append(one, root.Val)
res = one
for len(list) > 0 {
node := list[0]
list = list[1:]
one = one[1:]
if node.Left != nil {
list = append(list, node.Left)
two = append(two, node.Left.Val)
}
if node.Right != nil {
list = append(list, node.Right)
two = append(two, node.Right.Val)
}
if len(one) == 0 {
if len(two) != 0 {
res = two
}
one = two
two = []int{}
}
}
return res[0]
}