如何证明以下算法具有 O(nlogn) 时间复杂度
Posted
技术标签:
【中文标题】如何证明以下算法具有 O(nlogn) 时间复杂度【英文标题】:How do I demonstrate the following algorithm has O(nlogn) time complexity 【发布时间】:2019-10-21 14:18:28 【问题描述】:这是一种算法,它以 O(nlogn) 时间复杂度找到数组的最小降行数和行本身。练习的另一部分是使用这些降序行来实现耐心排序,它也必须是 O(nlogn)(即来自 c = 1 部分)。我不明白这两种情况下 logn 部分的来源。
#include <iostream>
#include <fstream>
#include <list>
using namespace std;
ifstream f("data.in");
int main()
int n, v[100];
f >> n;
for (int i = 0; i < n; i++)
f >> v[i];
list<int> aux;
aux.push_back(v[0]);
list<list<int> > rows;
rows.push_back(aux);
for (int i = 1; i < n; i++)
int selected = 0;
for (list<list<int> >::iterator it = rows.begin(); it != rows.end(); it++)
if (it->back() > v[i])
it->push_back(v[i]);
selected = 1;
break;
if (!selected)
list<int> aux;
aux.push_back(v[i]);
rows.push_back(aux);
for (list<list<int> >::iterator it = rows.begin(); it != rows.end(); it++)
for (list<int>:: iterator it2 = it->begin(); it2 != it->end(); it2++)
cout << *it2 << " ";
cout << endl;
int c = 1;
if (c == 1)
int s[100];
for (int i = 0; i < n; i++)
list<list<int> >::iterator it = rows.begin();
int minim = it->back();
it++;
while (it != rows.end())
if (!it->empty())
if (it->back() < minim)
minim = it->back();
it++;
it = rows.begin();
while (it != rows.end())
if (it->back() == minim)
it->pop_back();
if (it->empty())
rows.erase(it);
break;
it++;
s[i] = minim;
for (int i = 0; i < n; i++)
cout << s[i] << " ";
【问题讨论】:
我想是O(n^2)
?只考虑一个递增的输入序列。
添加到苹果苹果的评论中:您的代码的两个部分都可以改进为 O(n log n)。这可能就是您的导师所要求的。
【参考方案1】:
您的外部循环处理每条输入数据,因此增长是线性的,例如在)。您的内部循环仅处理完整输入数据的较小子集,并且增长是对数的,例如O(log n)。因此增长是线性的,例如O(nlogn)。如果内部循环处理每条输入数据,则增长将是二次的,例如O(n^2)
可以在这里找到一个很好的解释:
What does O(log n) mean exactly?
编辑:我的错误。我同意原帖下的 cmets 程序的增长似乎是 O(n^2)。我在转弯时有点快。快速浏览一下,最初在我看来,内循环执行了 log n 次。但看起来第二次 n 迭代中的内部循环并非如此。但是,据我了解,第一个内循环在我看来似乎被执行 log n 次(因此对行进行排序的增长顺序是 O(nlogn)),但也许我弄错了。
【讨论】:
以上是关于如何证明以下算法具有 O(nlogn) 时间复杂度的主要内容,如果未能解决你的问题,请参考以下文章
O(nlogn) + O(n) 的时间复杂度是不是只是 O(nlogn)?
最长递增子序列 LIS 时间复杂度O(nlogn)的Java实现