繁体   English   中英

在没有超时的情况下在庞大的数据集中找到最大的模式

[英]Find largest mode in huge data set without timing out

描述在统计学中,有一种分布的度量,称为众数。 众数是数据集中出现次数最多的数据。 一个数据集可能有多个模式,即有多个数据具有相同的出现次数。

Dengklek 先生给你 N 个整数。 找出数字的最大众数。

输入格式第一行包含一个整数 N。下一行包含 N 个整数。

输出格式一行包含一个整数,它是最大的模式。

输入示例6 1 3 2 4 1 4

示例输出4

限值1 ≤ N ≤100,000

1≤(第二行的每个整数)≤1000

#include <iostream>
#include <string>

using namespace std;

#define ll long long

int main() {

    unsigned int N;
    while(true){
        cin >> N;
        if(N > 0 && N <= 1000){
            break;
        }
    }
    int arr[N];
    int input;
    for (int k = 0; k < N; k++)
    {
        cin >> input;
        if(input > 0 && input <=1000){
             arr[k] = input;
        }
        else{
            k -= 1;
        }
    }
    
    int number;
    int mode;
    int position;
    int count = 0;
    int countMode = 1;

    for (int i = 0; i < N; i++)
    {
        number = arr[i];
        for (int j = 0; j < N; j++)
        {
            if(arr[j] == number){
                ++count;
            }
        }
        if(count > countMode){
            countMode = count;
            mode = arr[i];
            position = i;
        }
        else if(count == countMode){
            if(arr[i] > arr[position]){
                mode = arr[i];
                position = i;
            }
        }
        count = 0;
    }
    cout << mode << endl;
    
    return 0;
}

我得到了一个“RTE”(运行时错误)和 70 分。

这是我得到 80 分但得到“TLE”(超出时间限制)的代码:

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

#define ll long long

int main() {

    unsigned int N;
    while(true){
        cin >> N;
        if(N > 0 && N <= 100000){
            break;
        }
    }
    int arr[N];
    int input;
    for (int k = 0; k < N; k++)
    {
        cin >> input;
        if(input > 0 && input <=1000){
             arr[k] = input;
        }
        else{
            k -= 1;
        }
    }
    
    int number;
    vector<int> mode;
    int count = 0;
    int countMode = 1;

    for (int i = 0; i < N; i++)
    {
        number = arr[i];
        for (int j = 0; j < N; j++)
        {
            if(arr[j] == number){
                ++count;
            }
        }
        if(count > countMode){
            countMode = count;
            mode.clear();
            mode.push_back(arr[i]);
        }
        else if(count == countMode){
             mode.push_back(arr[i]);
        }
        count = 0;
    }
    sort(mode.begin(), mode.end(), greater<int>());
    cout << mode.front() << endl;
    
    return 0;
}

如何加速程序?

如前所述,在两个发布的片段中实现的算法具有 O(N 2 ) 时间复杂度,而存在 O(N) 替代方案。

您还可以利用标准库中的一些算法,例如std::max_element ,它返回一个

到范围 [first, last) 中最大元素的迭代器。 如果范围内的多个元素等价于最大元素,则返回迭代器到第一个这样的元素

#include <algorithm>
#include <array>
#include <iostream>

int main()
{
    constexpr long max_N{ 100'000L };
    long N;
    if ( !(std::cin >> N) or  N < 1  or  N > max_N  )
    {
        std::cerr << "Error: Unable to read a valid N.\n";
        return 1;
    }

    constexpr long max_value{ 1'000L };
    std::array<long, max_value> counts{};
    for (long k = 0; k < N; ++k)
    {
        long value;
        if ( !(std::cin >> value)  or  value < 1  or  value > max_value )
        {
            std::cerr << "Error: Unable to read value " << k + 1 << ".\n";
            return 1;
        }
        ++counts[value - 1];
    }
    
    auto const it_max_mode{ std::max_element(counts.crbegin(), counts.crend()) };
    // If we start from the last...                 ^^                ^^
    std::cout << std::distance(it_max_mode, counts.crend()) << '\n';
    // The first is also the greatest.
    return 0;
}

编译器资源管理器演示


我收到了“RTE”(运行时错误)

考虑第一个片段的这个片段:

int number;
int mode;
int position;            //   <---     Note that it's uninitialized
int count = 0;
int countMode = 1;

for (int i = 0; i < N; i++)
{
    number = arr[i];
    // [...] Evaluate count.
    if(count > countMode){
        countMode = count;
        mode = arr[i];
        position = i;   //  <---       Here it's assigned a value, but...
    }
    else if(count == countMode){    // If this happens first...
        if(arr[i] > arr[position]){
        //          ^^^^^^^^^^^^^      Position may be indeterminate, here  
            mode = arr[i];
            position = i;
        }
    }
    count = 0;
}

最后,一些值得一读的资源:

为什么是“使用命名空间标准;” 被认为是不好的做法?

为什么我不应该#include <bits/stdc++.h>?

使用预处理指令 #define for long long

为什么可变长度数组不是 C++ 标准的一部分?

你把事情复杂化了。 竞争性编程是一种奇怪的野兽,因为解决方案假设资源有限,输入数据量很大。 通常,这些任务是通过这种方式平衡的,它们需要使用恒定时间替代算法,即集合动态规划的总和。 通常会考虑代码的大小。 所以它结合了数学科学和肮脏的编程技巧。 这是专家的游戏,“脑色情”,如果你允许我这样称呼它:这是错误的,它很有趣,而且你正在使用你的大脑。 它与生产软件开发几乎没有共同之处。

您知道只能有 1000 个不同的值,但存在大量或重复的实例。 您所需要的只是找到最大的一个。 在 1000 的数组中找到最大值的最坏情况是什么? O(1000) 并且您当时检查一个。 并且您已经必须在 N 上进行循环才能输入这些值。

这是解决此问题的脏竞争代码示例(根本没有输入卫生):

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

using in = unsigned short;

array<int, 1001> modes;
in               biggest;
int              big_m;
int              N;

int main()
{   
    cin >> N;

    in val;
    while(N --> 0){
       cin >> val;
       if(val < 1001) { 
           modes[val]++; 
       }
       else 
           continue;
       if( modes[val] == big_m) {
           if( val > biggest )
               biggest  = val; 
       }
       else
       if( modes[val] > big_m) { 
           biggest  = val; 
           big_m =  modes[val];
       } 
    }
    
    cout << biggest;
    return 0;
}

如果您不需要它们,则没有 for 循环、简约的 id、要存储的简约数据。 如果可能,避免动态创建并尽量减少对象的自动创建,这些会增加执行时间。 静态对象在编译期间创建,并在加载可执行文件时具体化。

modes是我们的计数器阵列, biggest int对于给定的最大模式的商店最大值, big_m是当前最大值modes 因为它们是全局变量,所以它们是静态初始化的。

附注。 注意。 提供的示例是刻板印象的一个实例,我不保证它 100% 适合该特定法官或它使用的封闭测试用例。 一些评委使用受污染的输入和其他一些使挑战者的生活复杂化的东西,总是有一个未知的因素。 例如,如果判断将在输入值中提供“0”,即使值不在范围内,此示例也将忠实地输出“0”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM