二叉树_题目7:1026. 节点与其祖先之间的最大差值

63 阅读4分钟

题目7:1026. 节点与其祖先之间的最大差值

1026. 节点与其祖先之间的最大差值

同类题目

前置知识

题目描述

给定二叉树的根节点 root,找出存在于 不同 节点 AB 之间的最大值 V,其中 V = |A.val - B.val|,且 AB 的祖先。

(如果 A 的任何子节点之一为 B,或者 A 的任何子节点是 B 的祖先,那么我们认为 A 是 B 的祖先)

示例 1:

 输入:root = [8,3,10,1,6,null,14,null,null,4,7,13]
 输出:7
 解释: 
 我们有大量的节点与其祖先的差值,其中一些如下:
 |8 - 3| = 5
 |3 - 7| = 4
 |8 - 1| = 7
 |10 - 13| = 3
 在所有可能的差值中,最大值 7 由 |8 - 1| = 7 得出。

示例 2:

 输入:root = [1,null,2,null,0,3]
 输出:3

提示:

  • 树中的节点数在 25000 之间。
  • 0 <= Node.val <= 105

思路分析

递归每个节点,计算遍历到当前节点时的最大值、最小值及最大差值。计算过程可以从根节点到叶子节点,也可以从叶子节点到根节点。

  • 从根节点到叶子节点求每条路上的最大值与最小值,并使用局部变量记录每一次的最大值与最小值,往下传递最大值和最小值。
  • 从叶子节点到根节点求每条路上的最大值与最小值,并使用局部变量记录每一次的最大值与最小值,往上传递最大值和最小值。

程序代码

第一种方法:从根节点到叶子节点

 //https://leetcode.cn/problems/maximum-difference-between-node-and-ancestor/description/
 //1026. 节点与其祖先之间的最大差值
 ​
 class Solution {
 public:
     // 从根就开始传递最大值和最小值,使用mi 和 ma计录最小值和最大值
     // 往下递归的过程中和经过的节点进行比较
     int dfs(TreeNode *root, int mi, int ma) {
         if (root == nullptr) {
             return 0;
         }
         // abs(当前值 - 最小值) 和 abs(当前值 - 最大值) 选择差值最大的          
         int diff = max(abs(root->val - mi), abs(root->val - ma));
         mi = min(mi, root->val);
         ma = max(ma, root->val);
         // 递归左右
         diff = max(diff, dfs(root->left, mi, ma));
         diff = max(diff, dfs(root->right, mi, ma));
         return diff;
     }
 ​
     int maxAncestorDiff(TreeNode* root) {
         return dfs(root, root->val, root->val);
     }
 };

复杂度分析

时间复杂度O(N) 其中N为二叉树的节点数量。

空间复杂度: O(N) 最差情况下(二叉树退化为链表)。

代码优化

一条从根出发向下的路径,我们要计算的实际上是这条路径上任意两点的最大差值,递归到空节点时完整走完了这一条从根到叶子的路径。在递归的过程中,我们记录该路径上面的最大值和最小值,走完整个路径的时(叶子节点)再计算差值。

 //https://leetcode.cn/problems/maximum-difference-between-node-and-ancestor/description/
 //1026. 节点与其祖先之间的最大差值
 ​
 class Solution {
 private:
     int diff = 0;
 public:
     // 从根就开始传递最大值和最小值,使用mi 和 ma计录最小值和最大值
     // 往下递归的过程中和经过的节点进行比较
     void dfs(TreeNode *root, int mi, int ma) {
         if (root == nullptr) {
             // 叶子节点计算最大差值
             diff = max(diff,ma - mi);
             return;
         }
         // abs(当前值 - 最小值) 和 abs(当前值 - 最大值) 选择差值最大的          
         mi = min(mi, root->val);
         ma = max(ma, root->val);
         // 递归左右
         dfs(root->left, mi, ma);
         dfs(root->right, mi, ma);
     }
 ​
     int maxAncestorDiff(TreeNode* root) {
         dfs(root, root->val, root->val);
         return diff;
     }
 };

复杂度分析

时间复杂度O(N) 其中N为二叉树的节点数量,优化的是常数时间。

程序代码

第二种方法:从叶子节点到根节点

 //https://leetcode.cn/problems/maximum-difference-between-node-and-ancestor/description/
 //1026. 节点与其祖先之间的最大差值
 ​
 class Solution {
 private:
     // 记录最大差值
     int mx = 0;
 public:
     vector<int> travel(TreeNode* root)
     {
         // 记录返回值,num[0]为最大值,num[1]为最小值
         vector<int> num;
         if(root == nullptr)
         {
             num.push_back(-1);
             num.push_back(0x3f3f3f3f);
             return num;
         }
 ​
         vector<int> left = travel(root->left);
         vector<int> right =travel(root->right);
         
         // 返回的最大值、最小值和当前节点比较
         int mxnum = max(root->val,max(left[0],right[0]));
         int minnum = min(root->val,min(left[1],right[1]));
         // 获取反馈后的最大差值
         mx = max(max(root->val - minnum,mxnum - root->val),mx);
         
         // 将该树作为子树反馈到上一层
         num.push_back(mxnum);
         num.push_back(minnum);
 ​
         return num;
     }
     int maxAncestorDiff(TreeNode* root) {
         travel(root);
         return mx;
     }
 };
 ​

复杂度分析

时间复杂度O(N) 其中N为二叉树的节点数量。

空间复杂度: O(N) 最差情况下(二叉树退化为链表)。

题目感悟

二叉树可以从上往下传值,也可以从下往上返回值。从下往上比较繁琐。