程式碼隨想錄day18 || 530 二叉搜尋樹最小差,501 二叉搜尋樹眾數,236 二叉搜尋樹最近公共祖先

周公瑾55發表於2024-08-03

530 二叉搜尋樹最小差

var min int
var prev *TreeNode
func getMinimumDifference(root *TreeNode) int {
	// 二叉搜尋樹,中序遍歷比較相鄰兩個元素差,並返回最小絕對差
	min = math.MaxInt
	prev = nil
	inOrder(root)
	return min
}

func inOrder(root *TreeNode) {
	if root== nil{
		return
	}

	inOrder(root.Left)

	if prev != nil {
		v := root.Val - prev.Val
		if v < min {
			min = v
		}
	}
	prev = root

	inOrder(root.Right)
	return
}

501 二叉搜尋樹眾數


var maxCountVal map[int]int
func findMode(root *TreeNode) []int {
	// 出現二叉搜尋樹,優先考慮特性,即中序遍歷單調遞增
	// 出現眾數,中序遍歷相鄰節點出現次數

	// 重新初始化全域性變數
	maxCountVal = make(map[int]int)

	traversal(root, 1)
	var max int
	for _, v := range maxCountVal{
		if v > max {
			max = v
		}
	}

	var res []int
	for k, v := range maxCountVal{
		if v == max {
			res = append(res, k)
		}
	}

	return res
}

func traversal(root *TreeNode, count int) {
	// 什麼時候需要返回值,如果不需要遍歷整棵樹,或者需要判斷樹有某種條件(一條路徑)或者某個節點值,這時需要遍歷中有返回值
	// 本題條件需要遍歷整顆樹,並且已經設定了全域性變數作為接收,所以無需返回值

	if root == nil {
		return
	}

	traversal(root.Left, count)
	maxCountVal[root.Val]++
	traversal(root.Right, count)
	return
}

// 本質上遍歷,儲存成hash表,沒有用到二叉搜尋樹特性


var maxCountVal []int
var maxCount, count int
var prev *TreeNode
func findMode(root *TreeNode) []int {
	// 出現二叉搜尋樹,優先考慮特性,即中序遍歷單調遞增
	// 出現眾數,中序遍歷相鄰節點出現次數

	// 重新初始化全域性變數
	maxCountVal = []int{}
	maxCount = 0
	count = 1
	prev = nil
	traversal(root)

	return maxCountVal
}

func traversal(root *TreeNode) {
	// 什麼時候需要返回值,如果不需要遍歷整棵樹,或者需要判斷樹有某種條件(一條路徑)或者某個節點值,這時需要遍歷中有返回值
	// 本題條件需要遍歷整顆樹,並且已經設定了全域性變數作為接收,所以無需返回值

	if root == nil {
		return
	}

	traversal(root.Left)

	// 難點在於如何儲存眾數陣列,
	// 解決辦法就是,如果判斷當前count等於最大count,那麼就加入結果集,如果大於,清空結果集,加入此元素
	if prev != nil {
		// fmt.Println(root.Val, prev.Val, count)
		if root.Val == prev.Val {
			count++
		}else {
			count = 1
		}
	}

	// fmt.Println("=====",count, maxCount)

	if count == maxCount {
		maxCountVal = append(maxCountVal, root.Val)
	}else if count > maxCount {
		maxCountVal = append([]int{}, root.Val)
		maxCount = count
	}
	prev = root

	traversal(root.Right)
	return
}


236 二叉樹最近公共祖先

func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
	// 回溯,將子節點是否包含p,q的情況一一向上級返回,使用後序遍歷
	if root == nil {
		return nil
	}

	// 遇到目標節點直接向上級返回
	if root == p || root == q {
		return root
	}

	// 後序
	left := lowestCommonAncestor(root.Left, p, q)
	right := lowestCommonAncestor(root.Right, p, q)
	// 根節點即遞迴單層邏輯
	if left != nil && right != nil { // p, q 兩個目標節點分佈在此節點的左右子樹中,那麼由於是底層向上返回,所以此時root就是最近公共祖先
		return root
	}
	if left != nil && right == nil { // 如果左子樹出現目標節點,將目標節點向上返回,告訴更上級,左子樹出現了目標,
		// 此時可能兩種情況,1,直到最上級仍然右子樹沒出現目標節點,這時說明p-q是上下級,此時自己就是最近公共祖先
		// 2,返回到上級某一級,右子樹出現了另一個目標節點,此時就會進入上一個if判斷,直接返回上級是公共祖先
		return left
	}
	if left == nil && right != nil {
		return right
	}
	if left == nil && right == nil {
		return nil
	}
	return nil
}

相關文章