高级数据结构与算法期末考试速成记录

article/2025/7/28 2:50:13

高级数据结构与算法期末考试速成记录

0.分治中的一些知识点

Master公式(又称主定理,Master Theorem)是一种用于快速求解分治递归算法时间复杂度 的数学工具,适用于递归式形如以下形式的算法:
T ( n ) = a T ( n b ) + O ( n c ) 其中 a : 子问题被递归调用的次数 b : 将原问题分为了几个子问题 O ( n c ) : 分治之后合并所需要的时间复杂度 T(n)=aT(\frac{n}{b})+O(n^c)\\ 其中a:子问题被递归调用的次数\\ b:将原问题分为了几个子问题\\ O(n^c):分治之后合并所需要的时间复杂度 T(n)=aT(bn)+O(nc)其中a:子问题被递归调用的次数b:将原问题分为了几个子问题O(nc):分治之后合并所需要的时间复杂度
之后根据具体情况有着一下的结论:

  1. 如果 l o g b a < c log_b^a<c logba<c,时间复杂度为 O ( n c ) O(n^c) O(nc)
  2. 如果 l o g b a > c log_b^a>c logba>c时间复杂度为 O ( n l o g b a ) O(n^{log_b^a}) O(nlogba)
  3. 如果相等的话时间复杂度为 O ( n c × l o g n ) O(n^c\times log\ n) O(nc×log n)

快速排序中经常会用到的一个划分方法(就是根据给定的基准值,划分为小于,大于的两部分,返回基准的坐标值)的代码:

int part(int arr[],int l,int r)//其中r指向的是最后一个元素,不是n而是n-1
{int i=l,j=r+1;int shu=arr[l];//也可以使用随机划分,就是让随机选择的那个数和第一个数交换一下while(1){while(arr[++i]<shu && i<r) ;while(arr[--j]>shu);if(i>=j)break;swap(arr[i],arr[j]);}arr[l]=arr[j];arr[j]=shu;return j;
}

记住吧,因为错一点就会陷入死递归,或者划分错误!!!

1.分治算法之最近点对问题

问题描述:

给定平面上n个点的集合S,找其中的一对点,使得在n个点组成的所有点对中,该点对间的距离最小。

输入格式
:

第一行一个整数 n,表示点的个数。
接下来行,每行两个整数x,y,表示一个点的行坐标和列坐标。

输出格式:

仅一行,一个实数,表示最短距离,四舍五入保留4位小数。

测试链接

思路解析(作者自己的理解):

首先是利用分治,将点集不断的根据这个集合的横坐标的中位数划分==(分治),直到一个集合的点的数量为2或者3的时候,就是问题的basecase就可以直接得到这个分得的点集中最小的距离,之后也可以得到另一个小的点集中的最小的距离相比较,就可以得到两边各自的最短距离,之后取出最短的,把落在[mid-d,mid+d]的点开始遍历,根据这个鸽舍定理==不知道的可以去搜一下(简单来说在一定的条件下,一个点和跨越[mid-d,mid+d]的点只可能是6个).遍历[mid-d,mid+d]中的点,算距离他比较近的6个点即可(合并)(按照y排一个序),之后就可以得到答案.
代码示例:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
//定义点对
struct Point
{int x, y;
};
//获取两个点之间的距离
double getDis(Point& a, Point& b)
{return sqrt((a.x - b.x)*(a.x-b.x) + (a.y - b.y)*(a.y-b.y));
}
bool mcmp1(Point& a, Point& b)
{return a.x < b.x;
}
bool mcmp2(Point& a, Point& b)
{return a.y < b.y;
}
double f(Point arr[], int l, int r)
{if (r - l == 1)//两个点return getDis(arr[l], arr[r]);else if (r - l == 2)//三个点{double d1 = getDis(arr[l], arr[l + 1]);double d2 = getDis(arr[l + 1], arr[r]);double d3 = getDis(arr[l], arr[r]);if (d1 < d2){if (d1 < d3)return d1;else{return d3;}}else{if (d2 < d3)return d2;elsereturn d3;}}else{double ans = 0;int mid = (l + r) / 2;double d1=f(arr, l, mid);//左边最短距离double d2 = f(arr, mid + 1, r);//右边最短距离if (d1 < d2)ans = d1;elseans = d2;//下面求解跨越中间的答案//存放位于[mid-d,mid+d]的点,进行查找跨越中间的点的答案Point* brr = new Point[r - l + 4];int b = 0;for (int i = l; i <= r; i++)if (abs(arr[i].x - arr[mid].x) < ans)brr[b++] = arr[i];//按照y坐标排一个序sort(brr, brr + b, mcmp2);for (int i = 0; i < b; i++){//只需要找距离这个点最近的7个点即可.for (int j = i + 1; j <= i + 7 && j < b; j++){//如果y坐标就已经比找到的最小的d大了,就不需要往后找了,因为y越来越大if (brr[j].y - brr[i].y > ans)break;double tmp = getDis(brr[j], brr[i]);if (tmp < ans)ans = tmp;}}delete[]brr;return ans;}
}
int main()
{int n;cin >> n;Point arr[10005];for (int i = 0; i < n; i++){cin >> arr[i].x >> arr[i].y;}sort(arr, arr + n, mcmp1);//按照x从小到大排序,便于分治double res = f(arr, 0, n - 1);printf("%.4lf", res);
}

2.1动态规划之数字三角形

问题描述:

写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。

在这里插入图片描述

输入格式
第一个行一个正整数r,表示行的数目。
后面每行为这个数字金字塔特定行包含的整数。
输出格式
单独的一行,包含那个可能得到的最大的和。

题目链接

从后面往前面进行推答案即可,因为只考虑只有两行的时候可以非常容易的得到结果.定义转态:

dp[i][j]从第i行j列的数可以得到的最大的数字,

转态转移方程为:

d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i − 1 ] [ j + 1 ] ) + a r r [ i ] [ j ] . dp[i][j]=max(dp[i-1][j],dp[i-1][j+1])+arr[i][j]. dp[i][j]=max(dp[i1][j],dp[i1][j+1])+arr[i][j].

进一步可以使用空间压缩,使用一个一维数组不断更新答案,根据状态转移方程可知,这个位置的答案,只是依赖于上一个的相同列和列+1的最大值.故

转态转移方程变化为:

d p [ i ] = m a x ( d p [ i ] , d p [ i + 1 ] ) + a r r [ i ] [ j ] dp[i]=max(dp[i],dp[i+1])+arr[i][j] dp[i]=max(dp[i],dp[i+1])+arr[i][j].

那么结果就是 d p [ 0 ] dp[0] dp[0]

代码示例:

#include<bits/stdc++.h>
using namespace std;int main()
{int n;cin>>n;int arr[n+1][n+1]={0};for(int i=0;i<n;i++){for(int j=0;j<i+1;j++)cin>>arr[i][j];}int dp[n+2];//存放上一行的答案数组,不断的滚动更新for(int i=0;i<n;i++){dp[i]=arr[n-1][i];}for(int i=n-2;i>=0;i--){for(int j=0;j<=i;j++){dp[j]=max(dp[j],dp[j+1])+arr[i][j];}} cout<<dp[0]<<endl;}

2.2动态规划之矩阵连乘问题

题目描述
矩阵连乘问题:
给定n个矩阵{A,A2…,An} 其中 A i A_i Ai A i + 1 A_{i+1} Ai+1是可乘的( i = 1 , 2.. , n − 1 i=1,2..,n-1 i=1,2..,n1),确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。
输入
每组数据包括两行,第一行为数组长度n,第二行为存储矩阵维数的一维数组。因为相乘需满足列数和下一个矩阵的列数相等所以会输入一个数组
输出
矩阵连乘最优计算次数。
样例输入
7
30 35 15 5 10 20 25
样例输出
15125

没找到测试链接,找到的小伙伴可以在评论下面发一下,感谢💐💐💐💐

思路分析:

首先明确矩阵 A ( 大小为 i ∗ j ) A(大小为i*j) A(大小为ij)和矩阵 B ( j ∗ k ) B(j*k) B(jk)需要相乘的次数为 i × j × k i\times j \times k i×j×k

为方便起见,将连乘积 A i − 1 A i . . A j A_{i-1}Ai..A_j Ai1Ai..Aj;简记为 A [ i : j ] A[i:j] A[i:j],其中 A i A_i Ai的维度记为 p i − 1 × p i p_{i-1}×p_i pi1×pi。
若有一个计算 A [ 1 : k ] A[1:k] A[1:k]的次序所需的计算量更少,则会取代之。类似,计算 A [ k + 1 : n ] A[k+1:n] A[k+1:n]的次序也一定是最优的。
因此,矩阵连乘计算次序问题的最优解,包含了其子问题的最优解。

那么计算目的是求解 A [ 1 : n ] A[1:n] A[1:n]的最优解,而一个最优策略的子策略也应是最优的
所以问题可分解为求 A [ i : j ] A[i:j] A[i:j]的最优计算次序。

考察计算 A [ i : j ] A[i:j] A[i:j]的最优计算次序:
设这个计算次序在矩阵 A k 和 A k + 1 A_k和A_{k+1} AkAk+1之间将矩阵链断开, i ≤ k < j i≤k<j ik<j,则其相应加括号的方式为:KaTeX parse error: Unexpected character: '
' at position 35: …A_{k+1}...A_j;)
̲那么 A [ i : j ] A[i:j] A[i:j]的计算量为 A [ i : k ] A[i:k] A[i:k]的计算量加上 A [ k + 1 : j ] A[k+1:j] A[k+1:j]的计算量,再加上 A [ i : k ] A[i:k] A[i:k] A [ k + 1 : j ] A[k+1:j] A[k+1:j]
相乘的计算量 p i − 1 ∗ p k ∗ p j p_{i-1}*p_k*p_j pi1pkpj

设计算 A [ i : j ] , 1 ≤ i ≤ j ≤ n A[i:j],1≤i≤j≤n A[i:j],1ijn,所需要的最少数乘次数 d p [ i ] [ j ] dp[i][j] dp[i][j],则原问题的最优值为KaTeX parse error: Unexpected character: '
' at position 9: dp[1][n]
̲,当 i = j i=j i=j时,一个矩阵无法自己乘所以 d p [ i ] [ i ] = 0 , i = 1 , 2.. dp[i][i]=0,i=1,2.. dp[i][i]=0,i=1,2..
当 i < j i<j i<j时这里 A i A_i Ai, 的维数为 p i − 1 p i p_{i-1}pi pi1pi
可以得到动态转移方程:
d p [ i ] [ j ] = min ⁡ i ≤ k < j { d p [ i ] [ k ] + d p [ k + 1 ] [ j ] + p i − 1 ∗ p k ∗ p j } 其中 i < j dp[i][j]=\min_{i \le k < j} \{dp[i][k]+dp[k+1][j]+p_{i-1}*p_{k}*p_j\}其中i< j dp[i][j]=ik<jmin{dp[i][k]+dp[k+1][j]+pi1pkpj}其中i<j
代码示例:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 10;
int p[maxn], dp[maxn][maxn];
int main()
{int n;while (~scanf("%d", &n)){for (int i = 1; i <= n; ++i)scanf("%d", &p[i]);memset(dp, 0, sizeof(dp));for (int r = 2; r < n; ++r)//r个矩阵相乘{for (int i = 1; i < n - r + 1; ++i){int j = i + r - 1;//r个dp[i][j] = dp[i + 1][j] + p[i] * p[i + 1] * p[j + 1];for (int k = i + 1; k < j; ++k)dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + p[i] * p[k + 1] * p[j + 1]);}}printf("%d\n", dp[1][n - 1]);}return 0;
}

http://www.hkcw.cn/article/YrLjHfHaEH.shtml

相关文章

Telerik生态整合:Kendo UI for Angular组件在WinForms应用中的深度嵌入(一)

Telerik DevCraft包含一个完整的产品栈来构建您下一个Web、移动和桌面应用程序。它使用HTML和每个.NET平台的UI库&#xff0c;加快开发速度。Telerik DevCraft提供完整的工具箱&#xff0c;用于构建现代和面向未来的业务应用程序&#xff0c;目前提供UI for ASP.NET MVC、Kendo…

深入浅出程序设计竞赛(洛谷基础篇) 第十四章 搜索

文章目录 前言例14-1 四阶数独前置知识&#xff1a; 例14-2八皇后例14-3 kkksc03考前临时抱佛脚例14-4 马的遍历前置知识 例14-5 奇怪的电梯例14-6 Meteor Shower S习题14-1.1 选数例14-1 四阶数独前置知识&#xff1a; 例14-2八皇后例14-3 kkksc03考前临时抱佛脚例14-4 马的遍…

图书管理系统的设计与实现

湖南软件职业技术大学 本科毕业设计(论文) 设计(论文)题目 图书管理系统的设计与实现 学生姓名 学生学号 所在学院 专业班级 毕业设计(论文)真实性承诺及声明 学生对毕业设计(论文)真实性承诺 本人郑重声明:所提交的毕业设计(论文)作品是本人在指导教师的指导下,独…

【Java基础-环境搭建-创建项目】IntelliJ IDEA创建Java项目的详细步骤

在Java开发的世界里&#xff0c;选择一个强大的集成开发环境&#xff08;IDE&#xff09;是迈向高效编程的第一步。而IntelliJ IDEA无疑是Java开发者中最受欢迎的选择之一。它以其强大的功能、智能的代码辅助和简洁的用户界面&#xff0c;帮助无数开发者快速构建和部署Java项目…

医疗IT系统绝缘监测及故障定位,绝缘监测技术在医院关键区域的应用

医院作为重要的公共设施&#xff0c;其供配电系统的可靠性和安全性直接关系到患者的生命安全。为确保医院电力系统的稳定&#xff0c;GB/T 16895.24《建筑物电气装置》对医疗场所按用电的安全等级进行了细致的分类&#xff0c;并针对不同的类别推荐相应的电力系统配置。其中&am…

进程间通信及管道(理论)

目录 进程间通信介绍 进程间通信目的 进程间通信发展 进程间通信分类 管道 什么是管道 匿名管道 实例代码 用fork来共享管道原理 管道读写规则 管道特点 命名管道 创建一个命名管道 匿名管道与命名管道的区别 命名管道的打开规则 进程间通信介绍 进程间通信目的 数据传输&#…

如何安全地清洁 Windows10/11PC上的SSD驱动器

“我在 Windows 10 电脑上安装了新的 SSD&#xff0c;我要删除旧的 SSD 驱动器。但我不知道如何清洁电脑上的 SSD 驱动器。我想清除其中的所有内容。” 那么&#xff0c;您想知道如何在 Windows 10/11 PC 上清洁 SSD 驱动器吗&#xff1f;也许您只是想释放宝贵的空间并提高性能…

换ip是换网络的意思吗?怎么换ip地址

在数字化时代&#xff0c;IP地址作为我们在网络世界的"身份证"&#xff0c;其重要性不言而喻。许多人常将"换IP"与"换网络"混为一谈&#xff0c;实际上两者虽有联系却存在本质区别。本文将澄清这一概念误区&#xff0c;并详细介绍多种更换IP地址…

智能化能源管理系统在“双碳”背景下的新价值

安科瑞刘鸿鹏 摘要 2022年已并网的储能项目中,用户侧并网占比为8.36%,其中工商业储能规模为占比为98.6%。随着各省市的峰 谷价差拉大,部分省市可实现两充两放,工商业储能会更 加具有经济性,加上限电政策的影响,工商业储能将在 2023-2025年逐渐发展成主要的增长点&#xff…

带sdf 的post sim 小结

1.SDF文件主要内容 Delays&#xff08;module&#xff0c;device&#xff0c;interconnect&#xff0c;port&#xff09; Timing checks&#xff08;setup&#xff0c;hold&#xff0c;setuphold&#xff0c;recovery&#xff0c;removal&#xff0c;recrem&#xff09; Timing…

《JavaScript高级程序设计》读书笔记 34 - 代理基础

感谢点赞、关注和收藏! 上一篇类,这一篇进入书的第 9 章 - 代理与反射,首先是代理基础。 代理基础 代理是目标对象的抽象。从很多方面看,代理类似 C++指针,因为它可以用作目标对象的替身,但又完全独立于目标对象。目标对象既可以直接被操作,也可以通过代理来操…

《计算机仿真》——引领计算机仿真领域的学术前沿

期刊名称&#xff1a;计算机仿真 (Computer Simulation) 主办单位&#xff1a;中国航天科工集团公司第十七研究所 出版周期&#xff1a;月刊 出版地&#xff1a;北京市 语种&#xff1a;中文 开本&#xff1a;大16开 ISSN&#xff1a;1006-9348 CN&#xff1a;11-3724/TP 邮发代…

java-文件IO

文件IO 操作系统有一个专门的模块-文件系统&#xff0c;来管理文件。并提供了 api 供我们使用。 文件系统 使用 N叉树 来组织文件。 操作系统使用 “路径” 来描述文件的位置。路径的表示又分为 绝对路径 和 相对路径 绝对路径 &#xff1a;从树的的根节点&#xff08;Wind…

数据基座觉醒!大数据+AI如何重构企业智能决策金字塔(上)

1. 数据金字塔的千年进化史 1.1 从地窖到云端的存储革命 某家电企业在2010年遭遇库存危机时&#xff0c;市场部门需要三天才能从纸质单据中统计出全国滞销型号。当他们的数据工程师在2023年轻声唤醒对话式分析机器人&#xff0c;同样的需求响应时间缩短至9秒。 数据分层架构的…

【MySQL】事务及隔离性

目录 一、什么是事务 &#xff08;一&#xff09;概念 &#xff08;二&#xff09;事务的四大属性 &#xff08;三&#xff09;事务的作用 &#xff08;四&#xff09;事务的提交方式 二、事务的启动、回滚与提交 &#xff08;一&#xff09;事务的启动、回滚与提交 &am…

秒出PPT正式改名秒出AI,开启AI赋能新体验!

在现代办公环境中&#xff0c;借助智能工具提升工作效率已经成为趋势。秒出AI作为一款集AI PPT制作、动画、巨幕、视频、设计以及智能简历功能于一体的综合办公平台&#xff0c;为用户提供一站式智能内容生成解决方案&#xff0c;极大地简化了内容创作流程。 1. AI驱动的一键P…

白皮精读:214页数据安全治理白皮书6.0【附全文阅读】

《数据安全治理白皮书6.0》由中关村网络安全与信息化产业联盟数据安全治理专业委员会编著&#xff0c;北京安华金和科技有限公司参与。数据安全治理在数字化时代至关重要&#xff0c;关乎组织的生存与发展、个人信息权益保障以及国家的安全与稳定。这份白皮书围绕数据安全治理展…

工商业储能站能量管理系统

Acrel-2000MG 储能能量管理系统是安科瑞专门针对工商业储能 电站研制的本地化能量管理系统&#xff0c;可实现了储能电站的数据采集、数 据处理、数据存储、数据查询与分析、可视化监控、报警管理、统计 报表、策略管理、历史曲线等功能。其中策略管理&#xff0c;支持多种控制…

【JUC】深入解析 JUC 并发编程:单例模式、懒汉模式、饿汉模式、及懒汉模式线程安全问题解析和使用 volatile 解决内存可见性问题与指令重排序问题

单例模式 单例模式确保某个类在程序中只有一个实例&#xff0c;避免多次创建实例&#xff08;禁止多次使用new&#xff09;。 要实现这一点&#xff0c;关键在于将类的所有构造方法声明为private。 这样&#xff0c;在类外部无法直接访问构造方法&#xff0c;new操作会在编译…

智慧健康养老服务与管理实训室建设方案框架:服务流程与管理模式实训

随着智慧健康养老产业的快速发展&#xff0c;构建契合行业需求的实训室成为培养专业人才的关键。智慧健康养老服务与管理实训室建设方案聚焦服务流程与管理模式实训&#xff0c;旨在通过系统化设计&#xff0c;让学习者在仿真场景中掌握智慧健康养老服务的全链条操作与现代化管…