首页 > 其他分享 >数组形式组织的树

数组形式组织的树

时间:2023-06-14 10:35:41浏览次数:37  
标签:right TreeNode 组织 形式 nullptr 数组 res root left

引入

在 LeetCode 中,二叉树一般是以链表结点的形式组织的,定义如下:

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x): val(x), left(nullptr), right(nullptr) {}
};

其实也可以用数组的形式组织,即使用 $parent$ 数组,$y = parent[x]$ 说明 $y$ 是 $x$ 的父结点,根结点的父结点为 $-1$,表示父结点不存在。

最近公共祖先

链表形式

对链表形式树,求最近公共祖先可以使用递归很方便的解决:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (root == nullptr || root == p || root == q) {
            return root;
        }
        TreeNode *left = lowestCommonAncestor(root->left, p, q);
        TreeNode *right = lowestCommonAncestor(root->right, p, q);
        if (left != nullptr && right != nullptr) {
            return root;
        }
        if (left != nullptr && right == nullptr) {
            return left;
        }
        if (left == nullptr && right != nullptr) {
            return right;
        }
        return nullptr;
    }
};

也可以这样写,更好理解,与上面的写法的含义是一样的:

class Solution {
  public:
    pair<bool, bool> Ancestor(TreeNode *root, TreeNode *p, TreeNode *q, TreeNode **res) {
        if (root == nullptr) {
            return {false, false};
        }
        auto flagp = root == p, flagq = root == q;
        auto [pleft, qleft] = Ancestor(root->left, p, q, res);
        auto [pright, qright] = Ancestor(root->right, p, q, res);
        bool res_p = flagp || pleft || pright;
        bool res_q = flagq || qleft || qright;
        // 最近公共祖先的条件
        // 左子树,右子树都不是最近公共祖先
        if (res_p && res_q && !(pleft && qleft) && !(pright && qright)) {
            *res = root;
        }
        return {pleft || pright || flagp, qleft || qright || flagq};
    }
    TreeNode *lowestCommonAncestor(TreeNode *root, TreeNode *p, TreeNode *q) {
        TreeNode *res = nullptr;
        Ancestor(root, p, q, &res);
        return res;
    }
};

数组形式

对数组形式的树来说,求二叉树的最近公共祖先则要复杂很多。

我们需要以 1483. 树节点的第 K 个祖先 (Hard) 的解法作为先决条件,即先处理 $dp[i][j]$ 数组,其中 $dp[i][j]$ 表示编号 $i$ 结点的第 $2^j$ 个祖先的编号,则有递推公式: $dp[i][j] = dp[dp[i][j - 1]][j - 1]$。

处理好 $dp[i][j]$ 数组之后,我们可以用类似二分查找的办法确定编号为 $m$ 和编号为 $n$ 的结点的深度,这里深度可以定义为满足 $pars[i][k] = -1$ 的最小的 $k$,其中 $pars[i][k]$ 表示编号为 $i$ 结点的第 $k$ 个祖先的编号,可以由 $dp[i][j]$ 在 $O(\log n)$ 时间内求得。

对于求解公共祖先,其实我们也是用二分查找的思想求解,假设 $m$ 结点的深度为 $d_m$,$n$ 结点的深度为 $d_n$,且 $d_m >= d_n$(如果不满足,交换一下两个结点即可),那么等同于求 $n$ 的第 $k$ 个祖先 $p_n$ 以及 $m$ 的第 $k + d_m - d_n$ 个祖先 $p_m$ ,它们满足 $p_m = p_n$ 并且对应的 $k$ 最小。

预处理 $dp[i][j]$ 数组的时间复杂度为 $O(n\log n)$,总的时间复杂度为 $O(n\log n)$。

标签:right,TreeNode,组织,形式,nullptr,数组,res,root,left
From: https://www.cnblogs.com/zwyyy456/p/17479460.html

相关文章

  • 1814.统计一个数组中好对子的数目
    问题描述1814.统计一个数组中好对子的数目解题思路首先,变换一下题目的需求,nums[i]-rev(nums[i])==nums[j]-rev(nums[j]),然后利用哈希表记录每个值出现了多少次就可以了。代码classSolution{public:intrev(intnum){vector<int>tmp;inta......
  • 1877.数组中最大数对和的最小值
    问题描述1877.数组中最大数对和的最小值解题思路贪心将数组从小到大排序,最小最大配对,次小次大配对,依次配对,结果就是这些配对和的最大值。代码classSolution{public:intminPairSum(vector<int>&nums){sort(nums.begin(),nums.end());intres=......
  • 2357.使数组中所有元素都等于零
    问题描述2357.使数组中所有元素都等于零(Easy)给你一个非负整数数组nums。在一步操作中,你必须:选出一个正整数x,x需要小于或等于nums中最小的非零元素。nums中的每个正整数都减去x。返回使nums中所有元素都等于0需要的最少操作数。示例1:输入:nums=......
  • 【剑指Offer】1、二维数组中的查找
    【剑指Offer】1、二维数组中的查找题目描述:在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。解题思路:很明显,由于该二维数组上到下......
  • Redis入门 – Jedis存储Java对象 - (Java序列化为byte数组方式)
     Redis入门–Jedis存储Java对象-(Java序列化为byte数组方式) 在Jedis开发中,我们很多时候希望直接把一个对象放到Redis中,然后在需要的时候取出来。Redis的key和value都支持二进制安全的字符串,存储Java对象不是问题,下面我们看一下如何来实现。 1要存储的对象现在写一个很土的J......
  • golang对于[]byte数组转string进行比较的优化
    当需要比较两个[]byte数组是否相等时有好几种方案,下面可以看出前三种方案都是优化过的,效率高的方案。packagemainimport( "bytes" "crypto/rand" mr"math/rand" "testing")funcStringEqual(nint,ffunc(a,b[]byte)bool){ buf:=make([]byte,1024) rand.......
  • 数组
    <script>constarr=['a','b','c','d','e','f','g','h']//后面添加push删pop前面添加unshift删shift//slice截取console.log(arr.slice(1,3))//返回一个新数组,从1......
  • JS-数组和函数
    1.数组数组Array:是一种可以按顺序保存数据的数据类型1.1声明数组let数组名=[数据1,数据2,数据3,...,数据n]或let数组名=newArray(数据1,数据2,数据3,...,数据n)<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahtt......
  • 2170.使数组变成交替数组的最少操作数
    问题描述2170.使数组变成交替数组的最少操作数(Medium)给你一个下标从0开始的数组nums,该数组由n个正整数组成。如果满足下述条件,则数组nums是一个交替数组:nums[i-2]==nums[i],其中2<=i<=n-1。nums[i-1]!=nums[i],其中1<=i<=n-1。在一......
  • 442.数组中重复的数据 (Medium)
    问题描述442.数组中重复的数据(Medium)给你一个长度为n的整数数组nums,其中nums的所有整数都在范围[1,n]内,且每个整数出现一次或两次。请你找出所有出现两次的整数,并以数组形式返回。你必须设计并实现一个时间复杂度为O(n)且仅使用常量额外空间的算法解决此......