三、最大间隙(线性时间算法)

实验时间: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;
    }

    void 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(NumSize, a);//初始化NumSize个

        //遍历元素,
        for (auto i = 0, index = 0, temp = env.data[i]; i != NumSize; temp = env.data[i], ++i) {
            //找到下标,转为浮点数,在除,在乘,避免溢出
            index = 1.0 * (temp - min) / (max - min) * (NumSize - 1);
            ++b[index].count;
            if (temp > b[index].high) {//更新上界
                b[index].high = temp;
            }
            if (temp < b[index].low) {//更新下界
                b[index].low = temp;
            }
        }

        //res记录结果,lastHigh 记录前一个非空桶的上界,默认初始化为最小值
        int res = 0, lastHigh = min;
        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 ((b[i].low - lastHigh) > res) {
                    res = b[i].low - lastHigh;
                }
                lastHigh = b[i].high;//记录前一个非空桶的上界
            }
        }
        cout << "最大间隙为:\t" << res << endl;
    }
};

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;
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值