簡體   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