--- title: leetcode everyday author: Logic date: 2024-02-27 categories: [""] tags: [] draft: false --- ## day 1 2024-02-27 ### 543 Diameter of Binary Tree Given the root of a binary tree, return the length of the diameter of the tree. The diameter of a binary tree is the length of the longest path between any two nodes in a tree. This path may or may not pass through the root. The length of a path between two nodes is represented by the number of edges between them. ![0227W27EaKxHpjd2](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0227W27EaKxHpjd2.png) ### 题解 读题, 题目要求寻找二叉树中任意两节点之间的最大距离. 这时这个二叉树更像是一个图的性质而不是树, 即寻找图中任意两节点之间的最大距离. 考虑任意一点到另一点的距离等于其到另一点的父节点的距离减一, 则使用一个二维数组保存每个节点的两个属性: 1. 以该节点为根节点且经过该节点的最大直径 2. 以该节点为根节点的子树中叶子节点到该节点的最大距离 属性1可以通过将该节点的两个子节点的属性2加和并加1来计算. 属性2取两个子节点属性2的最大值并加1来计算. 最后遍历数组求得数组中属性1的最大值即可. 有一点动态规划的思想. 题目中并没有提供二叉树的节点总数, 则可以使用动态创建的方法, 在遍历过程中每遇到新节点就在二维数组中增加一项. 这里使用递归来对树进行后序遍历, 对空节点, 设置其属性2的值为-1, 这样保证叶子节点的属性2的值为0. 解题时遇到一个小bug, 使用了一个全局切片(数组)来保存变量时, 第一个测试用例的数据会保留到测试第二个测试用例的过程中, 这大概是因为leetcode的测试是对每个用例直接调用给出的解题入口函数, 因此需要在解题函数中将使用的全局变量初始化一下, 将数组设置为空后问题得到解决. ### 代码 ```go /** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */ var length [][]int func diameterOfBinaryTree(root *TreeNode) int { length = nil _ = postorder(root) max := -1 for _, value := range length{ if value[0] > max{ max = value[0] } } return max } func postorder(father *TreeNode) int { if father != nil{ len1 := postorder(father.Left) len2 := postorder(father.Right) len := make([]int,2) // find the max diameter pass through current node from the tree rooted current node len[0] = len1 + len2 + 2 len[1] = max(len1, len2) + 1 length = append(length, len) return len[1] } else { return -1 } } ``` ## day2 2024-02-28 ### 513. Find Bottom Left Tree Value Given the root of a binary tree, return the leftmost value in the last row of the tree. ![0228z98bIXZ3aQeQ](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0228z98bIXZ3aQeQ.png) ### 题解 找到二叉树最底层最左边的节点值, 用层序遍历遍历到最后一层找到最后一层最左边节点的值即可. 实现层序遍历可以使用一个队列, 将当前层节点的所有子节点入队后将当前层节点出队. 在go中可以使用切片实现一个队列. 使用一个标记变量记录当前层所有节点是否有子节点, 若无子节点则当前层为最低层, 返回当前层最左侧节点的值(此时队列中第一个节点的值). ### 代码 ```go /** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */ func findBottomLeftValue(root *TreeNode) int { queue := []*TreeNode{root} lowest := false key := -1 var father *TreeNode for !lowest{ queue = queue[key+1:] lowest = true for key, father = range queue{ if(father.Left != nil || father.Right != nil){ lowest = false if(father.Left != nil){ queue = append(queue, father.Left) } if(father.Right != nil){ queue = append(queue, father.Right) } } } } return queue[0].Val } ``` ### 总结 在题解中看到了一个使用深度优先搜索的方法, 记录当前搜索到的层级, 始终保存最大层级的第一个被搜索到的值, 因为使用的是后序遍历, 则每次遇到的当前层大于保存的最大层级时, 该节点就为新的最大层级的第一个节点, 即题目中要求的最左值(leftmost). 算法时间复杂度为O(n)------只遍历一次所有节点.