簡體   English   中英

std :: remove_if的漸近復雜度

[英]Asymptotic complexity of std::remove_if

我正在為一種具有硬編碼最大元素數N的數據結構的擦除方法而工作,該方法依賴於std::array來避免堆內存。 盡管std::array僅包含N個元素,其中M個是“相關的”元素,其中M小於或等於N。例如,如果N為10,則數組如下所示:

std::array<int, N> elements = { 0, 1, 2, -1, 4, -1, 6, -1, -1, 9 };

...如果M為7,則只有前7個元素是“相關的”,而其他元素則被視為垃圾(結尾{ -1, -1, -9 }是垃圾)。 我在這里將int用於SO示例,但實際程序存儲了實現operator==對象。 下面是一個有效的示例,該示例刪除所有-1並更新M:

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

constexpr unsigned N = 10;
unsigned           M = 7;
std::array<int, N> elements = { 0, 1, 2, -1, 4, -1, 6, -1, -1, 9 };

int main() {
        for (unsigned i = 0; i < M; ++i)
                std::cout << elements[i] << ' ';
        std::cout << '\n';

        auto newEnd = std::remove_if(
                std::begin(elements), std::begin(elements) + M,
                [](const auto& element) {
                        return -1 == element;
                }
        );

        unsigned numDeleted = M - std::distance(std::begin(elements), newEnd);
        M -= numDeleted;
        std::cout << "Num deleted: " << numDeleted << '\n';

        for (unsigned i = 0; i < M; ++i)
                std::cout << elements[i] << ' ';
        std::cout << '\n';

        return 0;
}

我的問題是std::remove_if的漸近復雜度是多少? 我可以想象在std::remove_ifstd::distance是整體O(2M)或O(M),其中std::remove_if是更昂貴的操作。 但是我不確定std::remove_if是否為O(N * M),因為每個刪除操作都會移動元素

編輯 :為清楚起見,我理解這應該將謂詞應用M次,但我想知道每次謂詞為真時是否都應用N個移位

通過cppreference

復雜度 :謂詞的std::distance(first, last)精確應用。

對移除的元素沒有移位操作,因為在調用std::remove_if之后它們可以具有未指定的值

編輯

回想起來,這個答案解決了一個比所提問題還要復雜的問題:如何在線性時間內實現“推回端”功能。 關於所要求的特定問題-與remove_if有關-@millenimumbug的答案可以更好地解決該問題。


我可以看到為什么您會認為復雜度為Θ(mn) ,因為m個移除的項目中的每一個可能都需要移動Θ(n)距離。

實際上有可能在時間Θ(n)和額外的O(1)空間(僅幾個額外的迭代器)中執行此操作。

考慮下圖,該圖顯示了算法的可能實現的迭代。

在此處輸入圖片說明

紅色項目是已識別項目的連續組,將要刪除到此為止(您只需要兩點即可記錄下來)。 綠色項目是現在正在考慮的項目(另一個指針)。

如果要刪除綠色項,則將紅色組包括在內就變得更大。 下圖顯示了該圖,紅色組在其中展開。 在下一次迭代中,綠色項目將在其右側。 在此處輸入圖片說明

如果不是,則所有紅色組都需要移過它。 有些想法可以說服您,這可以在紅色組的線性時間內完成(即使保證迭代器僅是正向迭代器)。

為什么復雜度是線性的? 因為您可以想象這等同於綠色元素相對於左組向左移動。 基本原理類似於攤銷分析的基本原理。

下圖顯示了第二種情況。 在下一次迭代中,綠色元素(正在考慮)將再次位於紅色組的右側。

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM