【数据结构和算法】高级数据结构

本文探讨了多种高级数据结构的使用,包括抽签问题的解决方案,如通过枚举、二分查找和优化的空间复杂度方法。介绍了熄灯问题的解决策略,并讲解了单调队列在处理滑动窗口最大值问题上的应用。此外,还涉及字典树、哈希表的题目及其解法,以及并查集、线段树和树状数组在处理数组操作中的作用。
摘要由CSDN通过智能技术生成


数据结构即是研究数据的各种 逻辑结构和 存储结构,以及在此基础上对数据的各种 操作

抽签问题

题目

将写有数字的n个纸片放入口袋中,从口袋中抽取4次纸片,记下纸片上的数字后将其放回口袋(可重复抽取同一纸片)。如果抽取4次后获得的数字之和为m,就算胜出。
编写一个程序判断当纸片上的数字是k1,k2,...,kn时,是否存在抽取4次之和为m的方案。

方法1

枚举每一种抽取方案,判断是否存在一种方案使得抽到的数字之和为m,即vi[i] + vi[j] + vi[k] + vi[h] == m

#include <iostream>
#include <vector>
using namespace std;

int main() {
   
	int n;
	int m;
	while (cin >> n >> m) {
   
		vector<int> vi(n);
		for (int i = 0; i < n; ++i) {
   
			cin >> vi[i];
		}
		
		bool f = false;
		for (int i = 0; i < n && !f; ++i) {
   
			for (int j = 0; j < n && !f; ++j) {
   
				for (int k = 0; k < n && !f; ++k) {
   
					for (int h = 0; h < n && !f; ++h) {
   
						if (vi[i] + vi[j] + vi[k] + vi[h] == m) {
   
							f = true;
						}
					}
				}
			}
		}
		
		if (f) {
   
			cout << "true" << endl;
		}
		else {
   
			cout << "false" << endl;
		}
	}
	return 0;
}

时间复杂度为O(N4)。

方法2

采用二分查找,判断是否存在vi[h] == m - vi[i] - vi[j] - vi[k]

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
   
	int n;
	int m;
	while (cin >> n >> m) {
   
		vector<int> vi(n);
		for (int i = 0; i < n; ++i) {
   
			cin >> vi[i];
		}
		
		sort(vi.begin(), vi.end());
		bool f = false;
		for (int i = 0; i < n && !f; ++i) {
   
			for (int j = 0; j < n && !f; ++j) {
   
				for (int k = 0; k < n && !f; ++k) {
   
					if (binary_search(vi.begin(), vi.end(), m - vi[i] - vi[j] - vi[k])) {
   
						f = true;
					}
				}
			}
		}
		
		if (f) {
   
			cout << "true" << endl;
		}
		else {
   
			cout << "false" << endl;
		}
	}
	return 0;
}

时间复杂度为O(N3logN)。

方法3

使用一个数组保存vi[i] + vi[j]vi[k] + vi[h]的所有结果,采用二分查找,判断是否存在vi[k] + vi[h] == m - vi[i] - vi[j]

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
   
	int n;
	int m;
	while (cin >> n >> m) {
   
		vector<int> vi(n);
		for (int i = 0; i < n; ++i) {
   
			cin >> vi[i];
		}
		
		vector<int> vin(n * n);
		for (int i = 0; i < n; ++i) {
   
			for (int j = 0; j < n; ++j) {
   
				vin[i * n + j] = vi[i] + vi[j];
			}
		}
		sort(vin.begin(), vin.end());
		
		bool f = false;
		for (int i = 0; i < n && !f; ++i) {
   
			for (int j = 0; j < n && !f; ++j) {
   
				if (binary_search(vin.begin(), vin.end(), m - vi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值