微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

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

先生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(N2) 时间复杂度,而存在 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;
}

Compiler Explorer demo


我收到了“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;
}

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

Why is “using namespace std;” considered bad practice?

Why should I not #include <bits/stdc++.h>?

Using preprocessing directive #define for long long

Why aren't variable-length arrays part of the C++ standard?

,

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

您知道只能有 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_mmodes 中的当前最大值。因为它们是全局变量,所以它们是静态初始化的。

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。