[Go版]算法通关村第五到十关总结——树和递归问题的套路和写法总结:层次遍历、前后序遍历、中序和二分查找

目录

  • 套路和写法总结
    • 层次遍历(Breadth-First Traversal)
    • 前序遍历(Preorder Traversal)
    • 后序遍历(Postorder Traversal)
    • 中序遍历(Inorder Traversal)
    • 二分查找(Binary Search)

套路和写法总结

学到这里,已经做了很多题目了,发现其中有模版存在的感觉。

层次遍历(Breadth-First Traversal)

层次遍历是按照树的层级顺序,从上到下逐层遍历节点。可以使用队列来辅助实现。

套路:

使用队列来存储当前层级的节点。
从根节点开始,将根节点入队。
循环遍历队列,依次出队节点,将其子节点入队。
重复上述步骤,直到队列为空。

func fn(root *TreeNode) [][]int {
  	ret := make([][]int, 0)
	if root == nil {
		return ret
	}
	queue := []*TreeNode{root}
	for len(queue) != 0 {
		length := len(queue)
		arr := make([]int, 0)
		for _, node := range queue {
			// 这里可以拿到当前层的每个节点,可以处理当前层所需业务逻辑
			arr = append(arr, node.Val)
			if node.Left != nil {
				queue = append(queue, node.Left)
			}
			if node.Right != nil {
				queue = append(queue, node.Right)
			}
		}
		queue = queue[length:]
		ret = append(ret, arr)
	}
	return ret
}

前序遍历(Preorder Traversal)

前序遍历是按照根-左-右的顺序遍历节点。

套路:

首先访问根节点。
递归地访问左子树。
递归地访问右子树。

func fn(root *TreeNode) []int {
	ret := make([]int, 0)
	if root == nil {
		return ret
	}
	//中
	ret = append(ret, root.Val)
	//左
	tmp := fn(root.Left)
	ret = append(ret, tmp...) 
	//右
	tmp = fn(root.Right)
	ret = append(ret, tmp...) 
	return ret
}

后序遍历(Postorder Traversal)

后序遍历是按照左-右-根的顺序遍历节点。在处理二叉树的释放资源等操作时常用到。

套路:

递归地访问左子树。
递归地访问右子树。
访问根节点。

中序遍历(Inorder Traversal)

中序遍历是按照左-根-右的顺序遍历节点。在二分搜索树中,中序遍历可以得到有序的节点序列。

套路:

递归地访问左子树。
访问根节点。
递归地访问右子树。

func fn(root *TreeNode) []int {
	ret := make([]int, 0)
	if root == nil {
		return ret
	}
	//左
	tmp := fn(root.Left)
	ret = append(ret, tmp...) 
	//中
	ret = append(ret, root.Val)
	//右
	tmp = fn(root.Right)
	ret = append(ret, tmp...) 
	return ret
}

二分查找(Binary Search)

二分查找是在有序数组中查找特定元素的有效方法。

套路:

初始化左右指针,分别指向数组的第一个和最后一个元素。
在每一步中,计算中间元素的索引。
比较中间元素与目标值的大小。
如果中间元素等于目标值,返回中间索引。
如果中间元素小于目标值,将左指针移动到中间元素的右边一位。
如果中间元素大于目标值,将右指针移动到中间元素的左边一位。
重复上述步骤,直到左指针大于右指针,表示未找到目标值。

二叉搜索树中寻找val值的节点

func fn(root *TreeNode, val int) *TreeNode {
	if root == nil {
		return nil
	}
	if root.Val == val {
		return root
	}
	if root.Val > val {
		return fn(root.Left, val)
	} else {
		return fn(root.Right, val)
	}
	return nil
}

有序数组中寻找val值的第一个索引和最后一个索引

func fn(nums []int, val int) int {
	length := len(nums)
	if length == 0 {
		return -1
	}
	return a(nums, val, 0, length-1)
}
func a(nums []int, val int, left int, right int) int {
	if left > right {
		return -1
	}
	mid := (right-left)>>1+left
	if nums[mid] == val {
		return mid
	}
	if nums[mid] > val {
		return a(nums, val, left, mid-1)
	} else {
		return a(nums, val, mid+1, right)
	}
	return -1
}

你可能感兴趣的:(算法与数据结构,golang,算法)