leetcode刷题记录07(2023-04-30)【二叉树展开为链表 | 买卖股票的最佳时机 | 二叉树中的最大路径和(递归) | 最长连续序列(并查集)】

114. 二叉树展开为链表

给你二叉树的根结点 root ,请你将它展开为一个单链表:

展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
展开后的单链表应该与二叉树 先序遍历 顺序相同。

示例 1

在这里插入图片描述

输入:root = [1,2,5,3,4,null,6]
输出:[1,null,2,null,3,null,4,null,5,null,6]

示例 2
输入:root = []
输出:[]

示例 3
输入:root = [0]
输出:[0]

提示:
树中结点数在范围 [ 0 , 2000 ] 内 树中结点数在范围 [0, 2000] 内 树中结点数在范围[0,2000]
− 100 < = N o d e . v a l < = 100 -100 <= Node.val <= 100 100<=Node.val<=100

进阶:你可以使用原地算法(O(1) 额外空间)展开这棵树吗?

现在刷leetcode经常一遍就可以通过,代码不需要调试,感觉还是很有成就感的,刷题确实有效果。

在这里插入图片描述

这道题目如果不要求使用原地算法(O(1) 额外空间),很简单,进行前序遍历,保存数组的指针到数组中,最后再进行一次树的重建,但是复杂度是O(n)。

或者采用一个栈的数据结构,保存一下右子树,不断地进行前序遍历,将当前节点添加到 pre->right 中,pre->left 中填写 nullptr

值得注意的是,需要对空子树进行处理,如果 root 节点为空,直接返回。

代码如下:

#include<stack>
using namespace std;// Definition for a binary tree node.
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:void flatten(TreeNode* root) {if (root == nullptr) {return;}stack<TreeNode*> stk;if (root->right != nullptr) {stk.push(root->right);}// 前驱节点TreeNode* pre = root;// 当前节点TreeNode* cur = root->left;while (!stk.empty() || cur != nullptr) {if (cur == nullptr) {cur = stk.top();stk.pop();}// 将右节点入栈if (cur->right != nullptr) {stk.push(cur->right);}// pre->rightpre->right = cur;pre->left = nullptr;pre = pre->right;// 更新 curcur = cur->left;}}
};

虽然采用栈降低了空间复杂度,但是也并不能说是O(1)级别的,看了下题解,思路是:对于每个节点,每次将它的左节点变为空,然后就移动到它的右节点上去。主要是找到左子树中最后一个访问的节点,将右子树移到它上面,最后再将左子树整体移动到 root->right 上。

代码如下:

class Solution {
public:void flatten(TreeNode* root) {TreeNode *curr = root;while (curr != nullptr) {if (curr->left != nullptr) {auto next = curr->left;auto predecessor = next;while (predecessor->right != nullptr) {predecessor = predecessor->right;}predecessor->right = curr->right;curr->left = nullptr;curr->right = next;}curr = curr->right;}}
};

121. 买卖股票的最佳时机

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

示例 1:
输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

示例 2:
输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0。

提示:
1 < = p r i c e s . l e n g t h < = 1 0 5 1 <= prices.length <= 10^5 1<=prices.length<=105
0 < = p r i c e s [ i ] < = 1 0 4 0 <= prices[i] <= 10^4 0<=prices[i]<=104

还是一遍过!

在这里插入图片描述

主要思路就是从前向后进行遍历,保存最小值,然后用当前值-最小值,如果大于当前的最大利润,就更新最大利润。最后返回最大利润。

代码如下:

#include<vector>
using namespace std;class Solution {
public:int maxProfit(vector<int>& prices) {int minVal = 0x3f3f3f3f;int profit = 0;for (int i = 0; i < prices.size(); i++) {if (prices[i] < minVal)minVal = prices[i];profit = profit > (prices[i] - minVal) ? profit : (prices[i] - minVal);}return profit;}
};

124. 二叉树中的最大路径和

二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。

路径和 是路径中各节点值的总和。

给你一个二叉树的根节点 root ,返回其 最大路径和 。

示例 1:

在这里插入图片描述

输入:root = [1,2,3]
输出:6
解释:最优路径是 2 -> 1 -> 3 ,路径和为 2 + 1 + 3 = 6

示例 2:

在这里插入图片描述

输入:root = [-10,9,20,null,null,15,7]
输出:42
解释:最优路径是 15 -> 20 -> 7 ,路径和为 15 + 20 + 7 = 42

提示:
树中节点数目范围是 [ 1 , 3 ∗ 1 0 4 ] 树中节点数目范围是 [1, 3 * 10^4] 树中节点数目范围是[1,3104]
− 1000 < = N o d e . v a l < = 1000 -1000 <= Node.val <= 1000 1000<=Node.val<=1000

很优美的代码,主要通过一个共享成员变量记录全局最优解,再 maxGain 内部有进行局部最优解的计算,并不断更新全局最优解。

同时,maxGain 的返回值,返回的是当前节点作为路径的一部分,要么要左子树,要么要右子树,不能两个都要(这样才能保证 同一个节点在一条路径序列中至多出现一次 )。

#include<algorithm>using namespace std;//  Definition for a binary tree node.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 {int maxSum = -0x3f3f3f3f - 1;int maxGain(TreeNode* root) {if (root == nullptr) {return 0;}int leftGain = max(maxGain(root->left), 0);int rightGain = max(maxGain(root->right), 0);int curMax = root->val + leftGain + rightGain;maxSum = max(maxSum, curMax);return root->val + max(leftGain, rightGain);}public:int maxPathSum(TreeNode* root) {maxGain(root);return maxSum;}
};

128. 最长连续序列

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。

示例 2:
输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9

提示:

0 < = n u m s . l e n g t h < = 1 0 5 0 <= nums.length <= 10^5 0<=nums.length<=105
− 1 0 9 < = n u m s [ i ] < = 1 0 9 -10^9 <= nums[i] <= 10^9 109<=nums[i]<=109

主要思路就是采用并查集来实现,首先要去重,得到一个哈希表,然后遍历这个哈希,如果存在连续的数,那么就需要进行合并,合并的时候要将大的数作为根,这样我们就将所有连续的数划分在一个集合里面了。

最后遍历一遍哈希表,判断当前元素是否为序列的第一个数。

  • 如果是第一个数,则找到它的祖先,根据祖先的值,就可以确定序列的长度。
  • 如果不是第一个数,不考虑。
#include<vector>
#include<unordered_map>
using namespace std;class Solution {vector<int> mergeAndFindSet;int find(int val) {while (mergeAndFindSet[val] != val){val = mergeAndFindSet[val];}return val;}void merge(int val1, int val2) {int i1 = find(val1);int i2 = find(val2);// 找到 i1 和 i2 后进行合并if (i1 == i2) return;mergeAndFindSet[i1] = i2;}
public:int longestConsecutive(vector<int>& nums) {unordered_map<int, int> mp;int n = nums.size();mergeAndFindSet = vector<int>(n, 0);for (int i = 0; i < n; i++) {mergeAndFindSet[i] = i;}for (int i = 0; i < n; i++) {mp[nums[i]] = i;}for (auto it = mp.begin(); it != mp.end(); it++) {int num = it->first;int i = it->second;if (mp.count(num + 1)) {        // 如果有连续的数就进行合并merge(i, mp[num + 1]);    // 合并需要将小的数合并到最大的根上}}int res = 0;for (auto it = mp.begin(); it != mp.end(); it++) {int num = it->first;int i = it->second;if (!mp.count(num - 1)) { // 如果当前这个数是最小的,寻找它的根int root = find(i);res = max(res, nums[root] - num + 1);}}return res;}
};

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

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

相关文章

AxGlyph安装教程

AxGlyph安装教程 AxGlyph是一款用于创建科学图表的强大工具&#xff0c;以下是AxGlyph的下载和安装步骤。 步骤一&#xff1a;下载AxGlyph 访问下载地址&#xff1a;点击下载 解压安装包 步骤二&#xff1a;运行安装程序 点击AxGlyph_Setup_Win7_8_10.exe进行安装 安装完成…

FHE简介

1. 引言 加密技术已经存在了数千年&#xff0c;用于相互发送秘密信息。例如&#xff0c;凯撒密码是最早的加密技术之一&#xff0c;可以追溯到公元前60年&#xff0c;其只由字母表中的字母交换组成。 随着互联网的出现&#xff0c;人们生成的私人数据量呈指数级增长&#xff…

【Maven】下载及配置

文章目录 1. 下载2. 解压3. 配置环境变量4. 验证 Maven 是一个跨平台的项目管理工具。作为 Apache 组织的一个颇为成功的开源项目&#xff0c;其主要服务于基于 Java 平台的项目创建&#xff0c;依赖管理和项目信息管理&#xff0c;是一个自动化构建工具&#xff0c;本文将介绍…

MySQL入门教程-触发器

9.触发器 什么是触发器 触发器(trigger)&#xff1a;监视某种情况&#xff0c;并进行某种操作&#xff0c;它的执行并不是程序调用&#xff0c;也不是手工启动&#xff0c;而是由事件来触发&#xff0c;例如&#xff1a;对一张表进行操作&#xff08;插入&#xff0c;更新&…

跨进程通信 macOS XPC 创建实例

一&#xff1a;简介 XPC 是 macOS 里苹果官方比较推荐和安全的的进程间通信机制。 集成流程简单&#xff0c;但是比较绕。 主要需要集成 XPC Server 这个模块&#xff0c;这个模块最终会被 apple 的根进程 launchd 管理和以独立进程的方法唤起和关闭&#xff0c; 我们主app 进…

JNPF开发平台--初体验

这一两年低代码的概念很流行&#xff0c;我也在网上了解体验了一番。 目前低代码主要分为两种&#xff0c;第一种是与云平台绑定的低代码&#xff0c;在云平台上开发&#xff0c;直接发布到云平台&#xff1b;第二种是低代码框架&#xff0c;低代码项目&#xff0c;这种比较流行…

C# 使用ZXing.Net生成二维码和条码

写在前面 条码生成是一个经常需要处理的功能&#xff0c;本文介绍一个条码处理类库&#xff0c;ZXing用Java实现的多种格式的一维二维条码图像处理库&#xff0c;而ZXing.Net是其.Net版本的实现。 在WinForm下使用该类库需要从NuGet安装两个组件&#xff1a; ZXing.Net ZXing…

当钉钉宜搭有销售单据或客户审批时,自动同步到畅捷通T+Cloud,赋能企业部门之间的业务流程自动化

1 场景描述 随着数字化转型&#xff0c;对于大规模的企业来说&#xff0c;都会选择低代码系统来搭建内部流程来提高公司的管理效率&#xff0c;例如使用钉钉宜搭作为企业的数据库&#xff0c;用来存储客户、供应商、单据等数据。也会使用畅捷通TCloud作为ERP系统解决管理财务、…

Github 2023-12-30 开源项目日报 Top10

根据Github Trendings的统计&#xff0c;今日(2023-12-30统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量TypeScript项目4JavaScript项目2C项目1Python项目1Java项目1HTML项目1Dart项目1非开发语言项目1 令人惊叹的 …

【51单片机系列】DS1302时钟模块扩展实验之与EEPROM结合使用只进行一次初始化工作

本文是关于时钟芯片DS1302的扩展实验。 文章目录 一、实验分析二、proteus仿真原理图三、软件设计及结果 本实验实现的目的&#xff1a;利用AT24C02掉电不丢失的功能&#xff0c;存储数据用来辨别DS1302时钟是否已经初始化&#xff0c;如果初始化就不执行DS1302初始化函数。 一…

ansible_角色的使用

本章主要介绍ansible中角色的使用 了解什么是角色独立地写一个角色使用角色系统自带角色地使用 1.了解角色 正常情况下&#xff0c;配置一个服务如 apache时&#xff0c;要做一系列的操作:安装、拷贝、启动服务等。如果要在不同的机器上重复配置此服务&#xff0c;需要重新执…

新品出击 | 软网关BLIoTLink免费发布

新品出击|软网关BLIoTLink免费发布 BLIoTLink是一款免费的物联网协议转换软件&#xff0c;可以部署在任何基于Linux OS的系统&#xff08;Linux、Debian、Ubuntu、FreeRTOS、RT-Thread&#xff09;中&#xff0c;使用灵活&#xff0c;可以实现数据的采集以及接入网络平台。 BL…

ssm基于JavaEE的智能实时疫情监管服务平台的设计与实现+jsp论文

摘 要 社会发展日新月异&#xff0c;用计算机应用实现数据管理功能已经算是很完善的了&#xff0c;但是随着移动互联网的到来&#xff0c;处理信息不再受制于地理位置的限制&#xff0c;处理信息及时高效&#xff0c;备受人们的喜爱。本次开发一套智能实时疫情监管服务平台有管…

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《面向平稳氢气需求的综合制氢系统鲁棒优化配置方法》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主的专栏栏目《论文与完整程序》 这个标题涉及到针对平稳氢气需求的综合制氢系统鲁棒优化配置方法。让我们逐步解读这个标题的关键要素&#xff1a; 面向平稳氢气需求&#xff1a; 这部分指…

k8s之kudeadm

kubeadm来快速的搭建一个k8s的集群&#xff1a; 二进制搭建适合大集群&#xff0c;50台以上主机 kubeadm更适合中小企业的业务集群 master&#xff1a;192.168.233.91 docker kubelet lubeadm kubectl flannel node1:192.168.233.92 docker kubelet lubeadm kubectl flannel…

Gin 源码深度解析及实现

介绍 什么是 gin &#xff1f; 一个轻量级高性能 HTTP Web 框架。 Introduction | Gin Web Framework (gin-gonic.com) Gin 是一个用 Go (Golang) 编写的 HTTP Web 框架。 它具有类似 Martini 的 API&#xff0c;但性能比 Martini 快 40 倍。 为什么使用 gin &#xff1f; In…

TP-LINK 路由器忘记密码 - 恢复出厂设置

TP-LINK 路由器忘记密码 - 恢复出厂设置 1. 恢复出厂设置2. 创建管理员密码3. 上网设置4. 无线设置5. TP-LINK ID6. 网络状态References 1. 恢复出厂设置 在设备通电的情况下&#xff0c;按住路由器背面的 Reset 按钮直到所有指示灯同时亮起后松开。 2. 创建管理员密码 3. 上网…

uni-appcss语法

锋哥原创的uni-app视频教程&#xff1a; 2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中..._哔哩哔哩_bilibili2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中...共计23条视频&#xff0c;包括&#xff1a;第1讲 uni…

Zookeeper之手写一个分布式锁

前言 我之前写了一篇快速上手ZK的文章&#xff1a;https://blog.csdn.net/qq_38974073/article/details/135293106 本篇最要是进一步加深学习ZK&#xff0c;算是一次简单的实践&#xff0c;巩固学习成果。 设计一个分布式锁 对锁的基本要求 可重入&#xff1a;允许同一个应…

跟小德学C++之配置文件(形式)

嗨&#xff0c;大家好&#xff0c;我是出生在达纳苏斯的一名德鲁伊&#xff0c;我是要立志成为海贼王&#xff0c;啊不&#xff0c;是立志成为科学家的德鲁伊。最近&#xff0c;我发现我们所处的世界是一个虚拟的世界&#xff0c;并由此开始&#xff0c;我展开了对我们这个世界…