【算法】算法设计与分析 期末复习总结

news2024/11/27 18:28:52

第一章 算法概述

  • 时间复杂度比大小,用代入法,代入2即可。
  • 求渐进表达式,就是求极限,以极限为O的括号;
  • O是指上界,Ω是指下界,θ是指上下界相等,在这里,可以这样理解:
  1. f(n) = O(g(n)) 意味着 g(n) 在 n 趋近于无穷大时比 f(n) 大;
  2. f(n) = Ω(g(n)) 意味着 g(n) 在 n 趋近于无穷大时比 f(n) 小;
  3. f(n) = θ(g(n)) 意味着 g(n) 在 n 趋近于无穷大时和 f(n) 同阶;

第二章 递归与分治

主定理要掌握,选择题必考:

填空有一道二分搜索,掌握简单版和改进版即可:

#include<bits/stdc++.h>
using namespace std;

const int N = 1e6 + 10;
int n, m, a[N], x;

int bisearch(int x, int a[], int left, int right) {
    if (left > right)
        return -1;
    int middle = (left + right) / 2;
    if (a[middle] == x)
        return middle;
    else if (a[middle] < x)
        return bisearch(x, a, left, middle - 1);
    else
        return bisearch(x, a, middle + 1, right);
}

int main() {
    cin >> n >> m;
    for (int i = 0; i < n; i++)
        cin >> a[i];
    while (m--) {
        cin >> x;
        cout << bisearch(x, a, 0, n - 1) <<endl;
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;

const int N = 1e6 + 10;
int n, m, a[N], x;

pair<int, int> bs(int x, int a[], int left, int right) {
	if (left > right) {
		pair<int, int> p(right, left);
		return p;
	}
	int middle = (left + right) / 2;
	if (a[middle] == x) {
		pair<int, int> p(middle, middle);
		return p;
	}
	else if (a[middle] < x)
		return bs(x, a, middle + 1, right);
	else
		return bs(x, a, left, middle - 1);
} 

int main() {
	cin >> n >> m;
	for (int i = 0; i < n; i++)
		cin >> a[i];
	while (m--) {
		cin >> x;
		pair<int, int> p = bs(x, a, 0, n - 1);
		cout << p.first << " " << p.second << endl;
	}
	return 0;
}

接着是排序,快速排序和归并排序的平均时间复杂度都为O(n logn),快排在最坏情况下的时间复杂度是O(n^2)。

知道中位数概念,一组个数为n的数中,当下标k = (n + 1) / 2时,称为找中位数。

归并的趟数是 logn ,归并的复杂度是 O(n logn)。

第三章 动态规划

0-1背包问题

题目

给定n(n<=100)种物品和一个背包。物品i的重量是wi(wi<=100),价值为vi(vi<=100),背包的容量为C(C<=1000)。
应如何选择装入背包中的物品,使得装入背包中物品的总价值最大? 在选择装入背包的物品时,对每种物品i只有两个选择:装入或不装入。不能将物品i装入多次,也不能只装入部分物品i。

输入格式:

共有n+1行输入:
第一行为n值和c值,表示n件物品和背包容量c;
接下来的n行,每行有两个数据,分别表示第i(1≤i≤n)件物品的重量和价值。

输出格式:

输出装入背包中物品的最大总价值。

输入样例:

在这里给出一组输入。例如:

5 10
2 6
2 3
6 5
5 4
4 6
输出样例:

在这里给出相应的输出。例如:

15
思路

假如现在有五个物品要选,这五个按顺序排下来,从第一个到第五个的最佳选择方案,相当于下面两种的择优选择:

  1. 不选第一个+后四个的最佳选择方案;
  2. 选第一个+后四个的最佳选择方案;

所以我们发现这是一个具有最优子结构性质的题目,同时也有重合子问题,于是我们可以用动态规划的方法来做。

作为动态规划,我们要严格按照三步走的格式来做:

首先,状态表示,我们设置一个二维数组m[i][j],作为从第i个到最后一个的最佳选择,同时剩余容量为j;

接着,递归方程,m[i][j] = max ( m[i + 1][j] , m[i + 1][j - w[i]] + v[i] ),也就是从不加第i个的,和加了第i个的这两个方案里选一个总价值最大的;

最后,边界条件,当我们的i为最后一个时,也就是i = n,此时容量从0到最大都可以进行赋值,也就是m[n][j] 的赋值,如果最后一个的重量不比c大,那就设置为这个的价值,如果比c小,就设置为0,注意边界条件在填表时要先写。

现在我们来研究一下最佳方案要怎么打印出来,也就是输出最佳选择组合的各个物品的下标。此时因为dp表已经填完了,所以可以让i从最小开始,我们依次判断即可,怎么判断呢?

直接看物品重量是否不超过剩余重量即可,剩余重量要另起一个变量remain,外层是物品的循环,里面第一重判断是有没有超重,第二重判断是加这个物品是不是比没加要好,把上面max里面的两个照抄即可。

都满足条件,就打印出这个物品的下标,然后使得remain减去这个物品的重量。

代码
#include<bits/stdc++.h>
using namespace std;

const int N = 100;

int n, c;
int w[N], v[N];
int m[N][N];

void dp() {
	for (int j = 0; j <= c; j++) {
		if (j >= w[n])
			m[n][j] = v[n];
		else
			m[n][j] = 0;
	}
	
	for (int i = n; i >= 1; i--) {
		for (int j = 0; j <= c; j++) {
			if (j >= w[i])
				m[i][j] = max(m[i + 1][j], m[i + 1][j - w[i]] + v[i]);
			else
				m[i][j] = m[i + 1][j];
		}
	}
	cout << m[1][c];
}

void print() {
	int remain = c;
	for (int i = 1; i <= n; i++) {
		if (remain >= w[i]) {
			if (m[i + 1][remain] < m[i + 1][remain - w[i]] + v[i]) {
				cout << i << ' ';
				remain -= w[i];
			}
		}
	}
	cout << endl;
}

int main() {
	cin >> n >> c;
	for (int i = 1; i <= n; i++)
		cin >> w[i] >> v[i];
	dp();
	print();
	return 0;
} 

第四章 贪心算法

选择当前看来最好的方案,这个的题目实在太简单了,不写思路。

题目

有n个人在一个水龙头前排队接水,假如每个人接水的时间为Ti,请编程找出这n个人排队的一种顺序,使得n个人的平均等待时间最小。

输入格式:

共两行,第一行为n(1≤n≤1000);第二行分别表示第1个人到第n个人每人的接水时间T1,T2,…,Tn,每个数据之间有1个空格。

输出格式:

输出为这种排列方案下的平均等待时间(输出结果精确到小数点后两位)。

输入样例:
10
56 12 1 99 1000 234 33 55 99 812
输出样例:
291.90

代码

#include<bits/stdc++.h>
using namespace std;

const int N = 1010;
int n;
int t[N];

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> t[i];
	sort(t + 1, t + n + 1);
	int total = 0;
	int wait = t[1];
	for (int i = 2; i <= n; i++) {
		total += wait;
		wait += t[i];
	}
	cout << fixed << setprecision(2) << 1.0 * total / n;
	return 0;
}

第五章 回溯法

子集和问题

题目

设集合S={x1,x2,…,xn}是一个正整数集合,c是一个正整数,子集和问题判定是否存在S的一个子集S1,使S1中的元素之和为c。试设计一个解子集和问题的回溯法,并输出利用回溯法在搜索树(按输入顺序建立)中找到的第一个解。

输入格式:

输入数据第1行有2个正整数n和c,n表示S的大小,c是子集和的目标值。接下来的1行中,有n个正整数,表示集合S中的元素。
是子集和的目标值。接下来的1 行中,有n个正整数,表示集合S中的元素。

输出格式:

输出利用回溯法找到的第一个解,以空格分隔,最后一个输出的后面有空格。当问题无解时,输出“No Solution!”。

输入样例:

在这里给出一组输入。例如:

5 10
2 2 6 5 4
输出样例:

在这里给出相应的输出。例如:

2 2 6

思路

这道题是在一堆数里面选择出一组加起来等于目标数的,用回溯法来做就是画出一棵二叉树,每一层树枝代表一个数字,如果选了这个数字,就顺着左子树往下走,没选就顺着右子树往下走,直到最底下,每次选择与否都要记录下来,还得记录当前的数字之和,如果走到叶子时数字之和等于目标数,就可以输出这组数了。

代码

#include<bits/stdc++.h>
using namespace std;

const int N = 1000;

int n, c; // 数字个数,目标数 
int a[N], x[N]; //保存数字的数组,表示数字被选与否状态的数组
int sum = 0, remain = 0; //当前已选数字之和,当前剩余数字之和

void backtrack(int t) {
	if (t > n) {
		if (sum == c) {
			for (int i = 1; i <= n; i++) {
				if (x[i] == 1) 
				    cout << a[i] << " ";
			}
			cout << endl;
			exit(0);
		}
		return;
	}
	
	remain -= a[t];
	if (sum + a[t] <= c) {
		x[t] = 1;
		sum += a[t];
		backtrack(t + 1);
		sum -= a[t];
	}
	if (sum + remain >= c) {
		x[t] = 0;
		backtrack(t + 1);
	}
	remain += a[t];
} 

int main() {
	cin >> n >> c;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		remain += a[i];
	}
	backtrack(1);
	cout << "No Solution!" << endl;
	return 0;
}

第六章 分支限界法

分支限界法和回溯法的区别:

回溯法的求解目标是找出解空间中满足约束条件的所有解,而分支限界法的求解目标是找出满足约束条件的一个解,或是在满足约束条件的解中找出使某一目标函数达到极大或极小的解,即在某种意义下的最优解;

回溯法以深度优先的方式搜索解空间,分支限界法则以广度优先或以最小耗费优先的方式搜索解空间,分支限界法的搜索策略是,在扩展结点处,先生成其所有子结点,再从当前的活结点表中选择下一个扩展结点。

6.1 分支限界法的基本思想

分支限界法与回溯法的主要区别在于它们对当前扩展结点所采用的扩展方式不同。

搜索方式是广度优先或最小耗费(最大效益)优先。

1. 队列式(FIFO)分支限界法

按队列的先进先出原则选取下一个结点为当前扩展结点。

2. 优先队列式分支限界法

按优先队列中规定的结点优先级选取优先级最高的下一个结点成为当前的扩展结点。

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

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

相关文章

覆盖与交换-第四十二天

目录 内存空间的扩充 覆盖技术 实例 交换技术 思考 本节思维导图 内存空间的扩充 历史背景&#xff1a;早期计算机内存很小&#xff0c;内存大小不够的情况解决办法&#xff1a;后来人们引入了覆盖技术&#xff0c;用来解决“程序大小超过物理内存总合”的问题 覆盖技术…

Elasticsearch:Serarch tutorial - 使用 Python 进行搜索 (二)

这个是继上一篇文章 “Elasticsearch&#xff1a;Serarch tutorial - 使用 Python 进行搜索 &#xff08;一&#xff09;” 的续篇。在今天的文章中&#xff0c;我们接着来完成如何进行分页及过滤。 分页 - pagination 应用程序处理大量结果通常是不切实际的。 因此&#xff0…

【QT 5 +Linux下+录屏软件使用+总结说明+使用录屏软件+简单软件使用+SimpleScreenRecorder+操作说明】

【【QT 5 Linux下录屏使用录屏软件简单软件使用SimpleScreenRecorder操作说明】】 1、前言2、实验环境3、录屏软件综述SimpleScreenRecorder&#xff1a;Kazam&#xff1a;OBS Studio (Open Broadcaster Software)&#xff1a;VokoscreenNG&#xff1a;RecordMyDesktop&#xf…

Spring 面试题学习笔记整理

Spring 面试题学习笔记整理 Spring的理解IOC读取 xml注入 配置过程解析注解注入过程 高频 &#xff1a;IOC 理解 及原理 底层实现IoC的底层实现高频&#xff1a;Bean的生命周期&#xff08;图解&#xff09;高频&#xff1a;Bean的生命周期&#xff08;文解&#xff09;扩展知识…

如何使用Cloudreve+Cpolar搭建个人PHP云盘系统并发布公网可访问

文章目录 1、前言2、本地网站搭建2.1 环境使用2.2 支持组件选择2.3 网页安装2.4 测试和使用2.5 问题解决 3、本地网页发布3.1 cpolar云端设置3.2 cpolar本地设置 4、公网访问测试5、结语 1、前言 自云存储概念兴起已经有段时间了&#xff0c;各互联网大厂也纷纷加入战局&#…

【自学笔记】01Java基础-08Java常用API:String、ArrayList集合

记录学习Java基础中有关应用程序接口&#xff08;API&#xff09;的基础知识&#xff0c;包括两个常用类String和ArrayList类的介绍。 什么是API&#xff1f; API是Application Programming Interface&#xff08;应用程序编程接口&#xff09;的缩写&#xff0c;它是一组预先…

陪诊系统|北京陪诊小程序提升陪诊服务效果

随着科技的不断发展&#xff0c;人们对于医疗服务的需求也越来越高。在过去&#xff0c;陪诊师和陪诊公司通常需要通过电话或传真等传统方式与医院进行沟通和安排。然而&#xff0c;现在有了陪诊小程序&#xff0c;这些问题得到了解决。本文将介绍陪诊小程序的开发流程和功能&a…

Python 简单爬虫程序及其工作原理

前言 网络中包含大量的数据&#xff0c;这些数据对于我们来说是非常有价值的&#xff0c;因此编写一个爬虫程序&#xff0c;自动从网页中获取所需的数据&#xff0c;对于信息收集和分析是非常有帮助的。Python 是一种高效而灵活的编程语言&#xff0c;它提供了强大的库和框架来…

SpringBoot学习(三)-整合JDBC、Druid、MyBatis

注&#xff1a;此为笔者学习狂神说SpringBoot的笔记&#xff0c;其中包含个人的笔记和理解&#xff0c;仅做学习笔记之用&#xff0c;更多详细资讯请出门左拐B站&#xff1a;狂神说!!! 一、整合JDBC使用&#xff08;理解&#xff09; 创建项目 勾选依赖启动器 查看依赖 …

vue3 插槽 slot 使用

vue3 插槽 slot 使用 在 Vue3 中&#xff0c;插槽&#xff08;slot&#xff09;是一种重要的组件复用和内容分发机制。通过使用插槽&#xff0c;可以让组件更加灵活和具有可复用性&#xff0c;在不同的地方渲染不同的内容&#xff0c;同时保证相同的样式。 插槽资料 官网介绍&…

【uniapp】多规格选择

效果图 VUE <template> <view><view class"wp-80 pd-tb-40 mg-auto"><button type"warn" click"showDrawer(showRight)">筛选</button></view><!-- 筛选-uni-drawer --><uni-drawer ref"s…

tolist()读取Excel列数据,(Excel列数据去重后,重新保存到新的Excel里)

从Excel列数据去重后&#xff0c;重新保存到新的Excel里 import pandas as pd# 读取Excel文件 file r"D:\\pythonXangmu\\quchong\\quchong.xlsx" # 使用原始字符串以避免转义字符 df pd.read_excel(file, sheet_namenameSheet)# 删除重复值 df2 df.drop_duplica…

HTTP打怪升级之路

新手村 上个世纪80年代末&#xff0c;有一天&#xff0c;Tim Berners-Lee正在工作&#xff0c;他需要与另一台计算机上的同事共享一个文件。他尝试使用电子邮件&#xff0c;但发现电子邮件不能发送二进制文件。Tim Berners-Lee意识到&#xff0c;他需要一种新的协议来共享二进制…

IntelliJ IDEA 如何配置git

在 IntelliJ IDEA 中配置 Git 的步骤如下&#xff1a; 打开 IntelliJ IDEA。找到 File–>Setting–>Version Control–>Git–>Path to Git executable。在 Git 的安装路径下找到 cmd 文件夹下的 git.exe&#xff0c;到此 Git 配置已完成。

Windows 安装配置 Anaconda、CUDA、cuDNN、pytorch-cuda全流程

Windows 安装配置 Anaconda、CUDA、cuDNN、pytorch-cuda全流程 1. 安装Anaconda 网址&#xff1a;https://repo.anaconda.com/archive/ 选择第一个下载即可 双击exe文件&#xff0c;按安装向导安装即可&#xff08;除安装路径自己选择外&#xff0c;其余均可按默认选项&#x…

02 Deep learning algorithm

Neural Networks target&#xff1a; inference&#xff08;prediction&#xff09;training my own modelpractical advice for building machine learning systemdecision Tress application: speech&#xff08;语音识别&#xff09; ----> images(计算机视觉)—> t…

【Redis-09】Redis哨兵机制的实现原理-Sentinel

Sentinel是Redis高可用性的解决方案&#xff1a;由一个或者多个Sentinel实例组成的哨兵系统监视多个主从服务器&#xff0c;并实现主从服务器的故障转移。 Sentinel本质上只是一个运行在特殊模式下的Redis服务器&#xff0c;使用以下命令可以启动并初始化一个Sentinel实例&…

面试题:聊聊 SpringBoot 中的 SPI 机制

文章目录 简介Java SPI实现示例说明实现类1实现类2相关测试 源码分析Spring SPISpring 示例定义接口相关实现 相关测试类输出结果源码分析 总结 简介 SPI(Service Provider Interface)是JDK内置的一种服务提供发现机制&#xff0c;可以用来启用框架扩展和替换组件,主要用于框架…

灸哥问答:数据结构对软件开发的作用

在软件开发的浩瀚海洋中&#xff0c;数据结构如同一座坚固的灯塔&#xff0c;为开发者指明方向&#xff0c;确保他们在构建复杂系统时不会迷失。数据结构不仅仅是编程的基础&#xff0c;更是高效、稳定、可扩展软件的核心。 一、提升算法效率 数据结构与算法紧密相连&#xf…

linux 使用iniparser读取.ini文件的配置信息

为什么要用项目配置文件 对于很多程序中要用的参数如果是可变的&#xff0c;那么最好的处理方式就是通过main(int argc,char **argv) 函数参数传递&#xff0c;或者从别的地方去获取&#xff0c;这其中之一就是配置文件&#xff0c;但是在一个成熟和架构完善的系统&#xff0c…