实验时间:10.28
目录
Puzzle 最大间隙问题
鸽笼原理
源代码:(只需要修改这几个参数即可)
Puzzle 最大间隙问题
给定 n 个无序实数 ,求这 n 个实数在实轴上相邻 2 个数之间的最大差值,要求线性的时间算法。
例如: 4? 11? 1? 9? 20? 2? 17
输出: 6
首先想到的就是排序,然后求差值,但是我目前已知的最快的排序算法,排序时间复杂度最少也要O(nlongn),因此只能使用别的巧妙算法了。
鸽笼原理
拓展鸽笼原理(抽屉原理),即为桶排序,在输入过程中找出数据的最大值max与最小值min_,在【min,max】区间内,将最大值与最小值之间进行均分成n-1份,每个区间的大小为 len = (max?- min)/(n-1),即此时为n-1个桶,将最大值最小值人为放置于第一个桶和最后一个桶中,分别代表了各自桶的下限和上限。根据这个判断剩余的n-2个元素放置的桶的位置,因为有n-1个桶需要放置n-2个元素所以根据抽屉原理必定有一个桶是空的,所以,最大间隙一定产生在两个不同区间之间(即两个桶之间,就是跨区间的数才可能产生最大的间隙 ),故最大的间隙一定是一个桶所放数据的最小值与另一个桶所放数据的最大值之间的差值。
简述算法过程:
桶需要一个上界,一个下界,一个次数,判断是否为空;
遍历元素找到最大值,最小值;
剩下 n - 2个数等分的放入 n - 1个桶,肯定有一个桶为空;
按顺序,求出所有空桶之间的上下界之差,然后选择一个最大差值即可。
实验结果(含时间、空间、输出结果):
?
源代码:(只需要修改这几个参数即可)
实验数据链接:
#include <iostream>
#include <fstream>
#include <ctime>
#include <string>
#include <vector>
using namespace std;
//FileNum为访问的文件数量,NumSize 为文件数据大小
const int FileNum = 3, NumSize = 10000;
//桶
struct Bucket {
int high;//上界
int low;//下界
int count;//次数,是否为空
};
class Env {
public:
int data[NumSize];
int pointer_max = 0;
int pointer = 0;
string s = "0";
Env(string str) {
s = str;
// test0.csv test1.csv test2.csv 共3个测试用例,请依次测试
cout << "文件 " << s << endl;
ifstream file("test_data/test_" + s + ".csv", ios::in);
if (!file.is_open())
cout << " 文件打开失败!" << endl;
string temp;
while (getline(file, temp)) {
data[pointer_max] = stoi(temp);
pointer_max++;
}
file.close();
}
};
// 所有的代码都需要写在 Algo 类内,自行定义其他需要的变量或函数
class Algo {
public:
Algo() {
cout << "algo ok" << endl;
}
int run(Env& env) {
//在此写入你的代码
//env.data 为目标数组
//遍历元素找到最大值,最小值;
//剩下 n - 2个数等分的放入 n - 1个桶,肯定有一个桶为空;
//按顺序,求出所有空桶之间的上下界之差,然后选择一个最大差值即可。
int max = env.data[0], min = max;
for (const auto& i : env.data) {
if (i > max) {
max = i;
} else if (i < min) {
min = i;
}
}
cout << "max:\t" << max << "\nmin:\t" << min << '\n';
Bucket a;
a.count = 0;
a.high = min;
a.low = max;
vector<Bucket> b;
//初始化 n - 1个桶
for (size_t i = 0; i != NumSize - 1; ++i) {
b.push_back(a);
}
//遍历元素,
for (int i = 0, index = 0, temp = env.data[i]; i != NumSize; temp = env.data[i], ++i) {
//找到下标
index = (NumSize - 1) * (temp - min) / (max - min);
b[index].count += 1;
if (temp > b[index].high) {//更新上界
b[index].high = temp;
}
if (temp < b[index].low) {//更新下界
b[index].low = temp;
}
}
//res记录结果,tempHigh 记录前一个非空桶的上界
int res = 0, tempHigh = 0;
bool isEmpty = false;
for (auto i = 0; i != b.size(); ++i) {
//cout << b[i].count << '\t' << b[i].high << '\t' << b[i].low << '\t' << endl;
if (b[i].count) {//不为空,记录high的值
//桶 非空 并且 当前桶的下界,减去,前一个的非空桶的上界,即为差值,然后判断,找到最大的差值
if (isEmpty && (b[i].low - tempHigh) > res) {
res = b[i].low - tempHigh;
}
//恢复状态,桶 不为空
isEmpty = false;
tempHigh = b[i].high;//记录前一个非空桶的上界
} else {//桶 为空,
isEmpty = true;
}
}
cout << "最大间隙为:\t" << res << endl;
return 0; //修改为返回正确的结果
}
};
int main() {
Env* env;
for (int i = 0; i != FileNum; i++) {
env = new Env(to_string(i));
Algo algo;
time_t start = clock();
algo.run(*env);
time_t end = clock();
cout << "程序耗时: " << double(end - start) / CLOCKS_PER_SEC << " ms" << endl;
cout << "占用内存:" << sizeof(algo) << " byte" << endl << endl;
delete env;
}
return 0;
}
|