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

news2024/12/23 18:37:20

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->right
            pre->right = cur;
            pre->left = nullptr;
            pre = pre->right;
            // 更新 cur
            cur = 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.coloradmin.cn/o/1343828.html

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

相关文章

ArcGIS批量计算shp面积并导出shp数据总面积(建模法)

在处理shp数据时&#xff0c; 又是我们需要知道许多个shp字段的批量计算&#xff0c;例如计算shp的总面积、面积平均值等&#xff0c;但是单个查看shp文件的属性进行汇总过于繁琐&#xff0c;因此可以借助建模批处理来计算。 首先准备数据&#xff1a;一个含有多个shp的文件夹。…

前后端分离nodejs+vue+ElementUi网上订餐系统69b9

课题主要分为两大模块&#xff1a;即管理员模块和用户模块&#xff0c;主要功能包括个人中心、用户管理、菜品类型管理、菜品信息管理、留言反馈、在线交流、系统管理、订单管理等&#xff1b; 运行软件:vscode 前端nodejsvueElementUi 语言 node.js 框架&#xff1a;Express/k…

Lumerical------按键中断程序执行

Lumerical------中断程序执行 引言正文 引言 在 Lumerical 中&#xff0c;很多时候我们需要通过 sweep 的方式来获取我们想要的结果&#xff0c;然而&#xff0c;有时候当我们运行程序后发现书写的脚本有问题时&#xff0c;我们想要强行终止程序的执行&#xff0c;该怎么办呢&…

代码随想录-刷题第四十二天

0-1背包理论基础 0-1背包问题介绍 0-1背包问题&#xff1a;有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品只能用一次&#xff0c;求解将哪些物品装入背包里物品价值总和最大。 0-1背包问题可以使用回溯法进…

Collector收集器的高级用法

Collectors收集器的高级用法 场景1&#xff1a;获取关联的班级名称 原先如果需要通过关联字段拿到其他表的某个字段&#xff0c;只能遍历List匹配获取 for (Student student : studentList) {Long clazzId student.getClazzId();// 遍历班级列表&#xff0c;获取学生对应班级…

【ArkTS入门】ArkTS开发初探:语言特点和开发特点

什么是ArkTS&#xff1f; ArkTS是一个为鸿蒙组件而生的框架&#xff0c;语法亲人好用。基于TypeScript&#xff0c;ArkTS拓展了声明式UI、状态管理等的能力&#xff0c;从本质上来讲&#xff0c;是TypeScript的扩展&#xff0c;主要服务于前端。 ArkTS的开发可以满足“一次开…

vue-cli3/webpack打包时去掉console.log调试信息

文章目录 前言一、terser-webpack-plugin是什么&#xff1f;二、使用配置vue-cli项目 前言 开发环境下&#xff0c;console.log调试信息&#xff0c;有助于我们找到错误&#xff0c;但在生产环境&#xff0c;不需要console.log打印调试信息&#xff0c;所以打包时需要将consol…

【React源码 - ReactDom.render发生了什么】

在React开发中&#xff0c;在入口文件我们都会执行ReactDom.render来讲整个应用挂载在主document中&#xff0c;那其中发生了什么&#xff0c;React是如何讲我们写的JSX代码&#xff0c;一步一步更新Fiber进而挂载渲染的呢。本文主要是基于react17.0.2的源码以及自己的理解来简…

thinkphp+vue+mysql企业车辆管理系统m117l

“企业车辆管理系统”是运用php语言和vue框架&#xff0c;以Mysql数据库为基础而发出来的。为保证我国经济的持续性发展&#xff0c;必须要让互联网信息时代在我国日益壮大&#xff0c;蓬勃发展。伴随着信息社会的飞速发展&#xff0c;企业车辆管理系统所面临的问题也一个接一个…

大数据背后的绿色收割:基于Hadoop的农产品价格信息智能分析

大数据背后的绿色收割&#xff1a;基于Hadoop的农产品价格信息智能分析 引言正文1. 数据获取与准备2. 数据清洗与处理3. Hadoop数据分析引擎的运用4. MySQL数据库的集成5. 创新性的可视化6. 结论与展望 结语 引言 随着信息技术的不断发展&#xff0c;农业领域也在数字化的浪潮…

C++ Primer Plus----第十二章--类和动态内存分布

本章内容包括&#xff1a;对类成员使用动态内存分配&#xff1b;隐式和显式复制构造函数&#xff1b;隐式和显式重载赋值运算符&#xff1b;在构造函数中使用new所必须完成的工作&#xff1b;使用静态类成员&#xff1b;将定位new运算符用于对象&#xff1b;使用指向对象的指针…

鸿蒙(HarmonyOS 3.1) DevEco Studio 3.1开发环境汉化

鸿蒙&#xff08;HarmonyOS 3.1&#xff09; DevEco Studio 3.1开发环境汉化 一、安装环境 操作系统: Windows 10 专业版 IDE:DevEco Studio 3.1 SDK:HarmonyOS 3.1 二、设置过程 打开IDE&#xff0c;在第一个菜单File 中找到Settings...菜单 在Setting...中找到Plugins…

毅速:一文说清3D打印随形水路的优势

3D打印发展如火如荼&#xff0c;对于模具行业来说&#xff0c;3D打印对模具水路的改变将产生哪些影响&#xff1f; 优化水路设计。通过3D打印技术&#xff0c;可以快速制造出复杂的内部结构和任意几何形状的模具&#xff0c;从而摆脱传统方法对水路加工的诸多限制。设计师可以…

准备用vscode代替sourceinsight

vscode版本1.85.1 有的符号&#xff0c;sourceinsight解析不到。 看网上说vscode内置了ripgrep&#xff0c;但ctrlshiftf在文件里查找的时候&#xff0c;速度特别慢&#xff0c;根本不像ripgrep的速度。ripgrep的速度是很快的。 但今天再查询&#xff0c;速度又很快了&#x…

mac node基本操作

1 查看所有版本 npm view node versions输出 2 查看已经安装的版本 n list3 安装指定版本 sudo -E n 16.0.04 切换版本 sudo n 16.0.05 查看版本 node -v

[ 云计算 | AWS ] 对比分析:Amazon SNS 与 SQS 消息服务的异同与选择

文章目录 一、前言二、Amazon SNS 服务&#xff08;Amazon Simple Notification Service&#xff09;三、Amazon SQS 服务&#xff08;Amazon Simple Queue Service&#xff09;四、SNS 与 SQS 的区别&#xff08;本文重点&#xff09;4.1 基于推送和轮询区别4.2 消费者数量对应…

2024年PMP考试新考纲-PMBOK第七版-【模型、方法和工件】真题解析

今天我们继续来看第七版PMBOK的考题&#xff0c;前面已经介绍了新考纲下最近几年价值交付系统、项目管理原则、项目绩效域、裁剪方面的部分真题和详细解析&#xff0c;今天来看PMBOK第七版的第四部分【模型、方法和工件】这个章节相关的真题。 PMBOK第七版中专门把模型、方法和…

在markdown中添加视频的两种方法

查看专栏目录 Network 灰鸽宝典专栏主要关注服务器的配置&#xff0c;前后端开发环境的配置&#xff0c;编辑器的配置&#xff0c;网络服务的配置&#xff0c;网络命令的应用与配置&#xff0c;windows常见问题的解决等。 文章目录 方式一源代码: 方式二结尾语网络的梦想 markd…

Android MVC 写法

前言 Model&#xff1a;负责数据逻辑 View&#xff1a;负责视图逻辑 Controller&#xff1a;负责业务逻辑 持有关系&#xff1a; 1、View 持有 Controller 2、Controller 持有 Model 3、Model 持有 View 辅助工具&#xff1a;ViewBinding 执行流程&#xff1a;View >…

STM32CubeMX教程8 TIM 通用定时器 - 输出比较

目录 1、准备材料 2、实验目标 3、实验流程 3.0、前提知识 3.1、CubeMX相关配置 3.1.1、时钟树配置 3.1.2、外设参数配置 3.1.3、外设中断配置 3.2、生成代码 3.2.1、外设初始化函数调用流程 3.2.2、外设中断函数调用流程 3.2.3、添加其他必要代码 4、常用函数 5…