【算法与数据结构】235、LeetCode二叉搜索树的最近公共祖先

news2024/12/26 23:41:01

文章目录

  • 一、题目
  • 二、解法
  • 三、完整代码

所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。

一、题目

在这里插入图片描述

二、解法

  思路分析:本题和这道题类似【算法与数据结构】236、LeetCode二叉树的最近公共祖先,相同的算法也能解这道题,但是没有充分利用到二叉搜索树的性质,二叉搜索树的性质为中间节点的键值大于所有左子树节点的键值,大于所有右子树的键值。因此要找到两个节点的最近祖先节点,只需要确定节点位于[p,q](或者是[q,p]大小未知,左闭右闭的区间)区间内。那么当节点键值比两个节点的键值都小时,说明公共最先节点在右子树内,遍历右子树即可,反之亦然,最终剩下的就是最近公共祖先节点
  程序如下

class Solution {
public:
    // 后序遍历: 左右中
    // 1、输入参数
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        // 2、终止条件
        if (root == NULL) return root;    // 如果节点相等或者是空节点返回

        // 3、单层递归逻辑
        if ((root->val > q->val && root->val > p->val)) {
            TreeNode* left = lowestCommonAncestor(root->left, p, q);    // 左
            if (left != NULL) return left;
        }
        if ((root->val < q->val && root->val < p->val)) {
            TreeNode* right = lowestCommonAncestor(root->right, p, q);    // 右
            if (right != NULL) return right;
        }   
        return root;
    }
};

三、完整代码

# include <iostream>
# include <vector>
# include <string>
# include <queue>
using namespace std;

// 树节点定义
struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
};

class Solution {
public:
    // 后序遍历: 左右中
    // 1、输入参数
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        // 2、终止条件
        if (root == NULL) return root;    // 如果节点相等或者是空节点返回

        // 3、单层递归逻辑
        if ((root->val > q->val && root->val > p->val)) {
            TreeNode* left = lowestCommonAncestor(root->left, p, q);    // 左
            if (left != NULL) return left;
        }
        if ((root->val < q->val && root->val < p->val)) {
            TreeNode* right = lowestCommonAncestor(root->right, p, q);    // 右
            if (right != NULL) return right;
        }   
        return root;
    }
};

// 前序遍历迭代法创建二叉树,每次迭代将容器首元素弹出(弹出代码还可以再优化)
void Tree_Generator(vector<string>& t, TreeNode*& node) {
    if (!t.size() || t[0] == "NULL") return;    // 退出条件
    else {
        node = new TreeNode(stoi(t[0].c_str()));    // 中
        if (t.size()) {
            t.assign(t.begin() + 1, t.end());
            Tree_Generator(t, node->left);              // 左
        }
        if (t.size()) {
            t.assign(t.begin() + 1, t.end());
            Tree_Generator(t, node->right);             // 右
        }
    }
}

template<typename T>
void my_print(T& v, const string msg)
{
    cout << msg << endl;
    for (class T::iterator it = v.begin(); it != v.end(); it++) {
        cout << *it << ' ';
    }
    cout << endl;
}

template<class T1, class T2>
void my_print2(T1& v, const string str) {
    cout << str << endl;
    for (class T1::iterator vit = v.begin(); vit < v.end(); ++vit) {
        for (class T2::iterator it = (*vit).begin(); it < (*vit).end(); ++it) {
            cout << *it << ' ';
        }
        cout << endl;
    }
}

// 层序遍历
vector<vector<int>> levelOrder(TreeNode* root) {
    queue<TreeNode*> que;
    if (root != NULL) que.push(root);
    vector<vector<int>> result;
    while (!que.empty()) {
        int size = que.size();  // size必须固定, que.size()是不断变化的
        vector<int> vec;
        for (int i = 0; i < size; ++i) {
            TreeNode* node = que.front();
            que.pop();
            vec.push_back(node->val);
            if (node->left) que.push(node->left);
            if (node->right) que.push(node->right);
        }
        result.push_back(vec);
    }
    return result;
}

// 前序遍历,找二叉树中指定的键值
TreeNode* traversal_preOrder(TreeNode* cur, int val) {
    if (cur == NULL) return NULL;
    if (cur->val == val) return cur;        // 中
    if (traversal_preOrder(cur->left, val) != NULL) return traversal_preOrder(cur->left, val);        // 左   
    if (traversal_preOrder(cur->right, val) != NULL) return traversal_preOrder(cur->right, val);     // 右  
    return NULL;
}

int main()
{
    // 构建二叉树
    vector<string> t = { "6", "2", "0", "NULL", "NULL", "4", "3", "NULL", "NULL", "5", "NULL", "NULL", "8", "7", "NULL", "NULL", "9", "NULL", "NULL" };   // 前序遍历
    my_print(t, "目标树");
    TreeNode* root = new TreeNode();
    Tree_Generator(t, root);
    vector<vector<int>> tree = levelOrder(root);
    my_print2<vector<vector<int>>, vector<int>>(tree, "目标树:");

    // 构建p, q节点
    int p = 2, q = 8;
    TreeNode* P_node = traversal_preOrder(root, p);
    TreeNode* Q_node = traversal_preOrder(root, q);

    // 找最近公共祖先节点
    Solution s;
    TreeNode* result = s.lowestCommonAncestor(root, P_node, Q_node);
    cout << "节点 " << P_node->val << " 和节点 " << Q_node->val << " 的最近公共祖先节点为 " << result->val << endl;

    system("pause");
    return 0;
}

end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1003230.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023-9-12 01背包问题

题目链接&#xff1a; 朴素版本 #include <iostream> #include <algorithm>using namespace std;const int N 1010;int n, m; int f[N][N]; int v[N], w[N];int main() {cin >> n >> m;for(int i 1; i < n; i) cin >> v[i] >> w[i];…

Java线上故障排查(CPU、磁盘、内存、网络、GC)+JVM性能调优监控工具+JVM常用参数和命令

CPU 原因包括业务逻辑问题(死循环)、频繁gc以及上下文切换过多。而最常见的往往是业务逻辑(或者框架逻辑)导致的&#xff0c;可以使用jstack来分析对应的堆栈情况。 使用jstack分析cpu问题 jstack主要用来查看某个Java进程内的线程堆栈信息 命令行参数说明&#xff1a; -l l…

ardupilot开发 --- 通信链路 篇

几个有意思的概图 飞控 以公司正在使用的 cuav Pixhawk V6X 为例 https://www.cuav.net/v6x/ 数传、飞控的mavlink连接 数传模块主要用于无人机于地面站共享数据&#xff0c;地面站通过数传可以获取无人机数据并且可以发送控制指令&#xff1b;与飞控的mavlink连接可以分为有…

文件压缩成压缩包,解压压缩包

压缩文件操作的工具类&#xff0c;压缩文件调用zip方法 package com.citicsc.galaxy.utils;import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration…

重磅:百度李彦宏、中科院曾毅入选,《时代周刊》AI最有影响力100人!

2023年9月8日&#xff0c;《时代周刊》发布了“2023年AI领域最有影响力100人” 榜单。 榜单权威吗&#xff1f; 有必要介绍下《时代周刊》。 《Time》&#xff08;时代周刊&#xff09;,1923年创刊于纽约&#xff0c;是美国公认的最重要的新闻杂志之一。《时代周刊》以报道精彩…

mybatis 中BigDecimal中的0存为null的坑

问题点: 做mybatis的插入和修改操作时&#xff0c;java中类型为Bigdicemal时&#xff0c;且值为0时&#xff0c;存入到数据库中的值为null&#xff0c;而不是0&#xff0c;其它的非0值正常 部分代码如下: 有问题的属性 可以看到是 Begdecimal 类型,对应查出来的日志如下: 可以…

chrome控制台怎么看hover的样式

​ 1. 悬浮显示是通过css控制台的 点击styles下面的 &#xff1a;hov&#xff0c;然后选中hover就可以了 2.如果是js控制的 js 失去悬浮以后&#xff0c;浮层就会隐藏&#xff0c;这个时候选中hover是没用的。 那怎么保留悬浮的状态呢&#xff0c;直接右键&#xff0c;会弹…

【Python】从入门到上头— 多线程(9)

进程和线程的区别 详见【Java基础】多线程从入门到掌握第一节(一.多线程基础) 一. _thread模块和threading模块 Python的标准库提供了两个模块&#xff1a;_thread和threading&#xff0c;_thread是低级模块&#xff0c;threading是高级模块&#xff0c;对_thread进行了封装。…

菜单组件Menu

前面讲解了如果构建GUI界面&#xff0c;其实就是把一些GUI的组件&#xff0c;按照一定的布局放入到容器中展示就可以了。在实际开发中&#xff0c;除了主界面&#xff0c;还有一类比较重要的内容就是菜单相关组件&#xff0c;可以通过菜单相关组件很方便的使用特定的功能&#…

在历史长河中,这个震撼了我!

在一个人的一生中&#xff0c;很容易低估世界发生的变化。 科技能够用我们无法想象的方式改变世界&#xff0c;直到它们真的发生。 咱们回顾这个世界的技术史&#xff0c;有助于看清楚未来几年甚至几十年内可能发生的改变。 我们的祖辈在童年时代&#xff0c;很难想象出会有一个…

从9.10拼多多笔试第四题产生的01背包感悟

文章目录 题面基本的01背包问题本题变式 本文参考&#xff1a; 9.10拼多多笔试ak_牛客网 (nowcoder.com) 拼多多 秋招 2023.09.10 编程题目与题解 (xiaohongshu.com) 题面 拼多多9.10笔试的最后一题&#xff0c;是一道比较好的01背包变式问题&#xff0c;可以学习其解法加深对…

手搓消息队列【RabbitMQ版】

什么是消息队列&#xff1f; 阻塞队列&#xff08;Blocking Queue&#xff09;-> 生产者消费者模型 &#xff08;是在一个进程内&#xff09;所谓的消息队列&#xff0c;就是把阻塞队列这样的数据结构&#xff0c;单独提取成了一个程序&#xff0c;进行独立部署~ --------&…

工具教程【甜心转译】-双语字幕、中文语音生成(配音),打破信息差

甜心转译 &#xff08;主站&#xff09;是一款AI加持的音/视频生成双语字幕、中文语音的软件。帮助人们更容易的获取外语信息、不管是学习、还是娱乐&#xff0c;快人一步。 主要功能 字幕生成&#xff1a;只需几个简单的步骤&#xff0c;轻松生成字幕。字幕翻译&#xff1a;…

【校招VIP】java语言考点之异常

考点介绍&#xff1a; 导致程序的正常流程被中断的事件&#xff0c;叫做异常。异常是程序中的一些错误&#xff0c;但并不是所有的错误都是异常&#xff0c;并且错误有时候是可以避免的。异常发生的原因有很多&#xff0c;通常包含以下几大类: 1.用户输入了非法数据。2.要打开的…

【Python】爬虫基础

爬虫是一种模拟浏览器实现&#xff0c;用以抓取网站信息的程序或者脚本。常见的爬虫有三大类&#xff1a; 通用式爬虫&#xff1a;通用式爬虫用以爬取一整个网页的信息。 聚焦式爬虫&#xff1a;聚焦式爬虫可以在通用式爬虫爬取到的一整个网页的信息基础上只选取一部分所需的…

首家!亚信科技AntDB数据库完成中国信通院数据库迁移工具专项测试

近日&#xff0c;在中国信通院“可信数据库”数据库迁移工具专项测试中&#xff0c;湖南亚信安慧科技有限公司&#xff08;简称&#xff1a;亚信安慧科技&#xff09;数据库数据同步平台V2.1产品依据《数据库迁移工具能力要求》、结合亚信科技AntDB分布式关系型数据库产品&…

pinduoduo(商品详情)API接口

为了进行电商平台 的API开发&#xff0c;首先我们需要做下面几件事情。 1&#xff09;开发者注册一个账号 2&#xff09;然后为每个pinduoduo应用注册一个应用程序键&#xff08;App Key) 。 3&#xff09;下载pinduoduo API的SDK并掌握基本的API基础知识和调用 4&#xff…

冠达管理:etf怎样购买?

ETF是一种指数基金&#xff0c;与传统的自动办理型基金不同&#xff0c;相比之下&#xff0c;ETF是一种被动出资东西&#xff0c;因为它们的方针是跟从某个特定的指数&#xff0c;而不是企图在市场上打败其他出资者。ETF通常具有较低的办理费用、较高的流动性和灵敏的买卖方法&…

CANoe的工作模式之争:模拟总线的两种运行方式

我们在文章《CANoe中的工作模式之争:由一段简单的代码引出的问题》中,介绍了模拟总线模式下的三种工作方式: animated with factoras fast as possibleslave mode由于模拟总线模式不需要连接真实ECU,无需和真实ECU保持时间同步,那么就可以在模拟总线上加速或放缓程序的运行…

pytorch从0开始安装

文章目录 一. 安装anaconda1.安装pytorch前需要先安装anaonda&#xff0c;首先进入官网&#xff08;Anaconda | The Worlds Most Popular Data Science Platform&#xff09;进行安装相应的版本。2.接着按如图所示安装,遇到下面这个选项时&#xff0c;选择all users.3.选择自己…