我想优化此循环。它的时间复杂度为 n 2 。我想要类似 n 或log( n )的东西。
for (int i = 1; i <= n; i++) {
for (int j = i+1; j <= n; j++) {
if (a[i] != a[j] && a[a[i]] == a[a[j]]) {
x = 1;
break;
}
}
}
a[i]
满足1 <= a[i] <= n
。
答案 0 :(得分:1)
这就是我会尝试的:
让我们用a [](即集合{a [i]})将图像称为B:B = {b [k]; k = 1..K,因此我存在,a [i] = b [k]}
对于每个b [k]值,k = 1..K,确定集合Ck = {i; a [i] = b [k]}。
B和Ck的确定可以在线性时间内完成。
然后让我们逐一检查集合Ck。
如果Card(Ck} = 1:k ++
如果Card(Ck)> 1:如果Ck的两个元素是B的元素,则x = 1;其他k ++
我将使用表(std::vector<bool>
)来存储1..N元素是否属于B。
我希望不要犯错。暂时没有时间编写程序。稍后我可以做,但我想您将能够轻松完成。
注意:发送此答案后,我发现@Mike Borkland在评论中已经提出了类似的建议...
答案 1 :(得分:1)
由于有时您需要查看学习的解决方案,因此我为您提供了一个小功能,可以完成您想要的工作。希望对您有所帮助。
#define MIN 1
#define MAX 100000 // 10^5
int seek (int *arr, int arr_size)
{
if(arr_size > MAX || arr_size < MIN || MIN < 1)
return 0;
unsigned char seen[arr_size];
unsigned char indices[arr_size];
memset(seen, 0, arr_size);
memset(indices, 0, arr_size);
for(int i = 0; i < arr_size; i++)
{
if (arr[i] <= MAX && arr[i] >= MIN && !indices[arr[i]] && seen[arr[arr[i]]])
return 1;
else
{
seen[arr[arr[i]]] = 1;
indices[arr[i]] = 1;
}
}
return 0;
}
好吧,这如何以及为什么起作用?首先,让我们看一下原始算法试图解决的问题;他们说,解决方案的一半是有充分陈述的问题。问题在于查找在给定的整数数组 A 中大小为 n 的元素是否绑定在一个和 n ([1, n ])在 A 中存在两个元素,即 x 和 y ,这样 x ! = y 和 Ax = Ay (位于索引 x 和 y 的数组, 分别)。此外,我们正在寻找一种具有好时间复杂度的算法,以便对于 n = 10000,该实现在1秒钟内运行。
首先,让我们开始分析问题。在最坏的情况下,需要至少一次对阵列进行完全扫描,以确定阵列中是否存在此类元素对。因此,我们不能比 O ( n )做得更好。但是,你会怎么做呢?一种可能的方法是扫描数组并记录是否出现给定的索引,这可以在另一个数组 B (大小为 n )中完成;同样,记录是否出现了与被扫描元素的索引处的 A 相对应的给定数字,这也可以在另一个数组 C 中完成。如果在扫描时数组的当前元素没有显示为索引,而是显示为元素,则返回yes。我不得不说,这是使用类似哈希表的数据结构的“经典技巧”。
原始任务是:i)降低时间复杂度(来自 O ( n ^ 2)),以及ii)确保实现在一个对于大小为10000的数组,则为1秒。建议的算法以 O ( n )的时间和空间复杂度运行。我用随机数组进行了测试,看来该实现的工作要比要求的快得多。
编辑:我的原始答案不是很有用,谢谢指出。检查完注释后,我认为代码可以有所帮助。
编辑2:我还添加了有关其工作原理的说明,因此可能很有用。希望对您有所帮助:)
答案 2 :(得分:-1)
我想优化此循环。它的时间复杂度为n 2 。我想要类似 n 或 log(n)的东西。
最简单的方法是首先对数组进行排序。这是 O(n log(n)),然后查找两个相邻元素的线性扫描也是 O(n),因此在时,主导复杂度不变> O(n log(n))。
您知道如何使用std::sort
,对吗?而且您知道复杂度是 O(n log(n))吗?
您可以弄清楚如何调用std::adjacent_find
,并且可以看到复杂度必须是线性的?
最佳的复杂度是线性时间。这仅允许我们对数组进行恒定数量的线性遍历。这意味着,如果我们需要进行查找以确定每个元素,那么我们是否之前就已经看到过该值-它必须是恒定时间。
您知道具有恒定时间插入和查找的任何数据结构吗?如果是这样,您可以编写一个简单的单遍循环吗?
提示:std::unordered_set
是固定时间成员资格测试的通用解决方案,Damien对std::vector<bool>
的建议对于您的特定情况可能更有效。