秋招突击——6/14——复习{(树形DP)树的最长路径}——新作{非递归求二叉树的深度、重复区间合并}

文章目录

    • 引言
    • 复习
      • 树形DP——树的最长路径
    • 新作
      • 使用dfs非递归计算二叉树的深度
      • 多个区间合并删除问题
        • 实现思路
        • 实现代码
        • 参考思路
    • 总结

引言

  • 这两天可能有点波动,但是算法题还是尽量保证复习和新作一块弄,数量上可能有所差别。

复习

树形DP——树的最长路径

  • 这道题是没有完全听完,但是到现在这个阶段,最起码得数组实现邻接链表做完。

无向图的一维数组表示邻接表实现

  • 首先说明一下,这里要使用邻接链表实现,这里是使用一维数组实现的邻接链表。
  • 同时这里是双向链表,所以,要加两次边,具体是实现如下

在这里插入图片描述

下面开始具体的分析

  • 树是一个确定的拓扑结构,每一个节点之间是是存在对应的父子关系,所以列觉路径可以更换为枚举中间节点,具体分析见下图,这是参考别人的,分析的很有道理

  • 通过红色节点的有三条路径

    • 红色路径,是一红色节点为根节点的最长的路径
    • 蓝色路径,是以红色节点为跟节点的最长路径和次长路径的和
    • 橙色路径,是红色节点的父节点的相同情况,具体见上图。
  • 相当于这道题,就是在遍历的过程中,计算对应的最长路径和子路径,然后在计算两者的和。

图片参考来源
在这里插入图片描述

动态规划分析

  • 这道题是两个动态规划,分别是动态规划计算最长的路径,次长的路径,而且是一个很明显的动态规划题目,就是子状态影响最终的状态。
  • 所以状态转移函数,就是计算的最长路径和次长路径,这里的动态规划,就是两个路径,f1[i]表示以节点i为根节点的最长路径,f2[i]表示以i为根节点的次长路径。具体如下

在这里插入图片描述
在这里插入图片描述

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;const int N = 10010;
int h[N],e[2*N],ne[2*N],w[2*N],idx;
int f1[N],f2[N],res; // f1保存最长的转移路径,f2保存次长的转移路径
int n;void add(int a,int b,int c){e[idx] = b;w[idx] = c;ne[idx] = h[a];h[a] = idx ++;
}void dfs(int r,int father){// 这里r是对应的根节点,father是对应的父节点f1[r] = 0,f2[r] = 0;for (int i = h[r]; ~i; i = ne[i]) {int j = e[i];  // 确定子节点的编号if (j == father)    continue;dfs(j,r);if(f1[j] + w[i] >= f1[r]) f2[r] = f1[r],f1[r] = f1[j] + w[i];else if(f1[j] + w[i] > f2[r]) f2[r] = f1[j] + w[i];}res = max(res,f1[r] + f2[r]);
}int main(){cin>>n;// 构建无向图memset(h,-1,sizeof(h));for (int i = 0; i < n -1; ++i) {int a,b,c;cin>>a>>b>>c;add(a,b,c),add(b,a,c);}// 遍历对应的无向图for (int i = h[1]; ~i; i = ne[i]) {cout<<1<<"  "<<e [i]<<endl;}cout<<res;return 0;
}
  • 这道题拖了那么久,乍一看,其实还是蛮简单的,思路只要清楚了,后续还是很好实现的,然后那个使用一维数组实现的邻接链表的,之前是没有做过,现在知道怎么用了,还是蛮简单的。

新作

使用dfs非递归计算二叉树的深度

  • dfs非递归二叉树高度,一开始写了个经典队列的bfs,意识到不对后开始改,最后没改完,就说了个暴力找到每个叶子的高度的思路。

  • 这个忘记的有点多,如果单纯使用栈来实现的话,就需要每一次入栈当前节点的子节点还有对应的深度,然后出栈,如果是叶子节点,就比较一下长度,如果不是,就继续做出栈和入栈的操作。

  • 这里实现的基本上和我写的比较类似

#include <iostream>
#include <stack>using namespace std;struct TreeNode{int val;TreeNode* left;TreeNode* right;TreeNode(int x):val(x),left(NULL),right(NULL){};
};// 生成样例
TreeNode* createSampleTree1() {TreeNode* root = new TreeNode(1);root->left = new TreeNode(2);root->right = new TreeNode(3);root->left->left = new TreeNode(4);root->left->right = new TreeNode(5);root->right->right = new TreeNode(6);root->left->left->left = new TreeNode(7);return root;
}int treeHeight(TreeNode* root){// 使用非递归的方式计算的树深度stack<pair<TreeNode *,int>> s;// 根节点入栈并重置深度s.push({root,1});int r = 0;// 出栈并遍历每一个节点的子节点while(!s.empty()){TreeNode* t = s.top().first;int l = s.top().second;s.pop();// 判定左子节点是否为空if (t->left)    s.push({t->left,l + 1});if (t->right)    s.push({t->right,l + 1});// 比较深度r = max(r,l);}return r;
}int main(){TreeNode* root = createSampleTree1();cout<<treeHeight(root);
}
  • 参考方法
    • 这里指的学习的是一个auto的使用,通过下述方式可以直接进行遍历使用。
auto [node, depth] = stack.top();
#include <iostream>
#include <stack>
#include <algorithm> // for maxstruct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};int treeHeight(TreeNode* root) {if (root == nullptr) return 0;std::stack<std::pair<TreeNode*, int>> stack;stack.push({root, 1});int maxHeight = 0;while (!stack.empty()) {auto [node, depth] = stack.top();stack.pop();if (node != nullptr) {maxHeight = std::max(maxHeight, depth);if (node->left != nullptr) stack.push({node->left, depth + 1});if (node->right != nullptr) stack.push({node->right, depth + 1});}}return maxHeight;
}int main() {// 示例二叉树TreeNode* root = new TreeNode(1);root->left = new TreeNode(2);root->right = new TreeNode(3);root->left->left = new TreeNode(4);root->left->right = new TreeNode(5);std::cout << "树的高度是: " << treeHeight(root) << std::endl;// 清理内存delete root->left->left;delete root->left->right;delete root->left;delete root->right;delete root;return 0;
}

多个区间合并删除问题

  • 这个也是在网上搜索的,部分拼多多主管面可能问到的题目,所以这里做一下,具体题目描述如下
给定一个n×2的二维数组,数组的每一行代表一个区间,
如果一个区间被另一个区间包含就删掉该区间,返回剩
下的所有区间。
* 比如: [1 2][1 ,3]包含。
实现思路
  • 这里是使用自定义排序实现的,如果包含关系,就将之按照包含的关系进行排序,然后在进行从前往后逐步进行遍历,对于相同的数组直接去除。最后剩下的就是对应的元素。
  • 自定义排序实现贪婪算法!
  • 这个方法确实是有问题的,有一部分样例是没有考虑到,不过背一下这个模版的。
实现代码
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;using Interval = pair<int,int>;vector<Interval> removeContainedIntervals(vector<Interval>& intervals){// 可以对区间进行排序,按照包含关系进行排序vector<Interval> res;sort(intervals.begin(),intervals.end(),[](auto a,auto b){if(a.first <= b.first && a.second >= b.second)    return 1;else return 0;});for (int i = 0;i < intervals.size();i ++) {Interval t = intervals[i];res.push_back(t);while((i + 1 < intervals.size())&& t.first <= intervals[i+1].first&& t.second >= intervals[i+1].second)i ++;}return res;
}int main() {vector<vector<Interval>> samples = {{{1, 4}, {2, 3}, {1, 3}, {4, 6}, {5, 7}},
//            {{1, 5}, {2, 4}, {6, 8}, {7, 9}, {5, 10}},
//            {{1, 2}, {3, 4}, {2, 3}, {1, 5}, {6, 7}},
//            {{1, 2}, {2, 3}, {3, 4}, {4, 5}},
//            {{1, 3}, {2, 6}, {8, 10}, {15, 18}}};for (size_t i = 0; i < samples.size(); ++i) {vector<Interval> result = removeContainedIntervals(samples[i]);cout << "样例 " << i + 1 << " 剩余的区间为:" << endl;for (const auto& interval : result) {cout << "[" << interval.first << ", " << interval.second << "] ";}cout << endl;}return 0;
}
参考思路
  • 这里是一个贪心算法解决区间问题的模板,需要好好练习一下,和我的方法差不多,只不过他是针对单边进行排序的
  • 这里是使用标准区间进行比较的,会更加灵活方便一点,比我的方法要好很多。
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;// 定义一个区间类型
using Interval = pair<int, int>;// 比较函数,用于排序区间
bool compareIntervals(const Interval &a, const Interval &b) {if (a.first == b.first) {return a.second < b.second;}return a.first < b.first;
}vector<Interval> removeContainedIntervals(vector<Interval>& intervals) {// 如果区间列表为空,直接返回空列表if (intervals.empty()) {return {};}// 按照起始点排序,起始点相同则按照终止点排序sort(intervals.begin(), intervals.end(), compareIntervals);vector<Interval> result;Interval last = intervals[0]; // 初始化第一个区间作为比较基准for (size_t i = 1; i < intervals.size(); ++i) {// 如果当前区间不被上一个区间包含if (intervals[i].first > last.first && intervals[i].second > last.second) {result.push_back(last); // 保留上一个区间last = intervals[i];    // 更新比较基准} else {// 如果当前区间的终止点更长,更新比较基准if (intervals[i].second > last.second) {last = intervals[i];}}}// 最后一个区间也需要保留result.push_back(last);return result;
}int main() {vector<vector<Interval>> samples = {{{1, 4}, {2, 3}, {1, 3}, {4, 6}, {5, 7}},{{1, 5}, {2, 4}, {6, 8}, {7, 9}, {5, 10}},{{1, 2}, {3, 4}, {2, 3}, {1, 5}, {6, 7}},{{1, 2}, {2, 3}, {3, 4}, {4, 5}},{{1, 3}, {2, 6}, {8, 10}, {15, 18}}};for (size_t i = 0; i < samples.size(); ++i) {vector<Interval> result = removeContainedIntervals(samples[i]);cout << "样例 " << i + 1 << " 剩余的区间为:" << endl;for (const auto& interval : result) {cout << "[" << interval.first << ", " << interval.second << "] ";}cout << endl;}return 0;
}

总结

  • 复习的那个最长路径,还是蛮简单的,今天终于看懂了,继续加油吧。明天可以快速写一下。
  • 今天算是做了两道新的题目,dfs获取树的深度那道题,是自己做出来的,然后区间合并的那道题,是参考别人的,不过看了题解,加油吧!明天把题目再过一遍!

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

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

相关文章

Visual Studio Code 的安装教程和配置C语言环境插件推荐

目录 1.vscode简介2.下载安装vs code3.VSCode基础配置VSCode界面简介VSCode设置中文界面VSCode个性化设置VSCode常用设置基本编辑快捷键VSCode常用快捷键 4.下载安装MinGW5.设置vscode里的环境6.插件推荐7.vscode官方文档 1.vscode简介 VSCode是微软出的一款轻量级编辑器&…

WordPress实时搜索插件Ajax Search Lite,轻松替代默认搜索功能

WordPress自带的默认搜索功能是跳转到搜索结果页&#xff0c;如果你想要实时搜索功能&#xff0c;特别是在问答中心显示搜索功能&#xff0c;那么建议使用这个WordPress实时搜索插件Ajax Search Lite&#xff0c;它可以在文章、页面、自定义类型文章中搜索标题、内容、摘要、自…

八爪鱼现金流-022-mybatis插件加密和国密SM4算法

背景&#xff1a; 用户的金额数据&#xff0c;不希望被别人看到。 业务场景分析&#xff1a; 用户在页面上添加金额数据 -----> 服务器内存&#xff08;加密、解密&#xff09; -----> 存储数据库 调研及结果&#xff1a; 使用mybatis的拦截器插件&#xff0c;进行数…

LeetCode | 168.Excel表列名称

这道题一开始以为是简单的进制转换问题&#xff0c;用的以往的思路&#xff0c;对于一般性的进制转换题目&#xff0c;只需要不断地对 columnNumber 进行 % 运算取得最后一位&#xff0c;然后对 columnNumber 进行 / 运算&#xff0c;将已经取得的位数去掉&#xff0c;直到 col…

vue 渲染函数 h jsx

h 是什么 vue 提供的创建虚拟 DOM 节点 (vnode)的函数。 https://cn.vuejs.org/api/render-function.html#h jsx 是什么 JSX是 JavaScript XML&#xff08;HTML&#xff09;的缩写&#xff0c;表示在 JS 代码中书写 HTML 结构。简单理解就是&#xff1a; JSXjavascript xml&am…

机器学习:数据分布的漂移问题及应对方案

首先&#xff0c;让我们从一位高管告诉我的一个故事开始&#xff0c;很多读者可能对此感同身受。 大约两年前&#xff0c;他的公司聘请了一家咨询公司开发一个机器学习模型&#xff0c;帮助他们预测下周每种食品杂货需要多少&#xff0c;以便他们可以相应地补货。这家咨询公司…

PostgreSQL基础(十四):PostgreSQL的数据迁移

文章目录 PostgreSQL的数据迁移 PostgreSQL的数据迁移 PostgreSQL做数据迁移的插件非常多&#xff0c;可以从MySQL迁移到PostgreSQL也可以基于其他数据源迁移到PostgreSQL。 这种迁移的插件很多&#xff0c;这里只说一个&#xff0c;pgloader&#xff08;非常方便&#xff0…

Vulnhub-DC-9

靶机IP:192.168.20.144 kaliIP:192.168.20.128 网络有问题的可以看下搭建Vulnhub靶机网络问题(获取不到IP) 信息收集 nmap扫描一下端口及版本号 dirsearch扫目录 最后去前端界面观察发现也没什么隐藏路径。 观察功能&#xff0c;search引起注意&#xff0c;SQL注入测试 当输…

PPT: Pre-trained Prompt Tuning for Few-shot Learning

文章汇总 当前的问题 当前的学者(a)、(b)、©都是通过微调模型(encoder/decoder)来适应下游任务。尽管效果很好&#xff0c;但是一方面代价很大&#xff0c;一方面在小样本设置下&#xff0c;微调模型这种做法性能差得多。本文的想法&#xff1a;通过一些预训练任务仅冻结…

SringBoot 如何使用HTTPS请求及Nginx配置Https

SringBoot 如何使用HTTPS请求及Nginx配置Https SringBoot 如何使用HTTPS请求生成证书导入证书及配制创建配置类将pfx转成.key和.pem Nginx 安装SSL依赖./configure 安装依赖编译安装完openssl后报了新错 Nginx配置 SringBoot 如何使用HTTPS请求 生成证书 由于业务数据在传输过…

十分钟学会微调大语言模型

有同学给我留言说想知道怎么训练自己的大语言模型&#xff0c;让它更贴合自己的业务场景。完整的大语言模型训练成本比较高昂&#xff0c;不是我们业余玩家能搞的&#xff0c;如果我们只是想在某个业务场景或者垂直的方面加强大模型的能力&#xff0c;可以进行微调训练。 本文…

51交通灯

一、基本原理 利用51单片机控制各个路口红绿灯及时间显示。 设计的重点&#xff1a; 1、各个路口红绿灯亮灭的规则&#xff0c;暂不考虑左转方向&#xff1b; 2、倒计时的实现&#xff0c;利用单片机的定时器进行计数得到秒信号&#xff1b; 3、时间显示&#xff1a;东西南…

【LLM之RAG】Adaptive-RAG论文阅读笔记

研究背景 文章介绍了大型语言模型&#xff08;LLMs&#xff09;在处理各种复杂查询时的挑战&#xff0c;特别是在不同复杂性的查询处理上可能导致不必要的计算开销或处理不足的问题。为了解决这一问题&#xff0c;文章提出了一种自适应的查询处理框架&#xff0c;动态选择最合…

LeetCode | 434.字符串中的单词数

这道题直接使用语言内置的 split 函数可直接分离出字符串中的每个单词&#xff0c;但是要注意区分两种情况&#xff1a;1、空串&#xff1b;2、多个空格连续&#xff0c;分割后会出现空字符的情况&#xff0c;应该舍弃 class Solution(object):def countSegments(self, s):&qu…

通过MATLAB实现PID控制器,积分分离控制器以及滑模控制器

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 通过MATLAB实现PID控制器,积分分离控制器以及滑模控制器。通过对比三个算法可知&#xff0c;采用滑模控制算法&#xff0c;其具有最快的收敛性能&#xff0c;较强的鲁棒性&…

机器学习:人工智能的子领域之一

引言 人工智能&#xff08;AI&#xff09;已经成为现代科技的重要组成部分&#xff0c;推动了许多领域的创新与进步。在人工智能的诸多子领域中&#xff0c;机器学习&#xff08;ML&#xff09;无疑是最关键和最具影响力的一个。机器学习通过自动分析和学习数据中的模式&#x…

react 0至1 案例

/*** 导航 Tab 的渲染和操作** 1. 渲染导航 Tab 和高亮* 2. 评论列表排序* 最热 > 喜欢数量降序* 最新 > 创建时间降序* 1.点击记录当前type* 2.通过记录type和当前list中的type 匹配*/ import ./App.scss import avatar from ./images/bozai.png import {useState} …

云电脑有多好用?适合哪些人使用?

云电脑作为一种新型的计算模式&#xff0c;其应用场景广泛且多样&#xff0c;适合各类人群使用。云电脑适合什么人群使用&#xff1f;云电脑有哪些应用场景&#xff1f;有什么好的云电脑推荐&#xff1f;以下本文将详细探讨云电脑的主要应用场景及其适用人群的相关内容&#xf…

基于单片机的数控稳压开关电源研究

为了解决多种类供电的电压需求&#xff0c;克服供电电路体积大、性价比低的问题&#xff0c;复杂电路系统以单片机控制为核心&#xff0c;尝试构建单片机数控开关稳压电源的硬件平台&#xff0c;并开发软件程序&#xff0c;实现系统多种类供电电压输出的控制。实验证明&#xf…

ARM单片机使用CAN总线部署BootLoader

1.引言 1.1.单片机开发BootLoader意义 单片机开发BootLoader的原因主要与其在嵌入式系统中的关键作用有关。BootLoader是硬件启动的引导程序&#xff0c;它在操作系统内核或用户应用程序运行之前执行。以下是单片机开发BootLoader的主要原因&#xff1a; 初始化硬件设备&…