使用分而治之的数组的第二大元素

Posted

技术标签:

【中文标题】使用分而治之的数组的第二大元素【英文标题】:Second greatest element of an array using divide and conquer 【发布时间】:2019-11-05 01:09:31 【问题描述】:

我编写了这个函数来查找数组的第二大元素,但我对它的时间复杂度有些怀疑。 if 条件有 θ(1) 还是增加了递归调用的时间复杂度?

从实验角度来看,它不应大于分治策略时间复杂度的最大最大元素。

int secondmax(int arr[], int first , int last)
   if(first+1==last) return arr[first];
   int mid= first +(last-first)/2;
   int left = secondmax(arr, first, mid);
   int right = secondmax(arr, mid, last);
   if(  (left > right ? left : right) > max1)
      max2=max1;
      max1= left > right ? left : right;
   

    else if((left > right ? left : right) > max2  &&     (left > right ? left : right) != max1)
       max2= left > right ? left : right;

   
   return left > right ? left : right;

ps max1, max2 是全局变量,可能我可以删掉 max1

【问题讨论】:

如果条件。是 theta(1),过客,我收藏了,不错 qn。 您应该始终在此处返回一个 2 元组,因为如果它们都是第二个最大值,那么您可能会在此处选择第三个最大值。 如果您可以将编译器从不必要的计算负载中解救出来,那就更好了。例如,在您的情况下,left > right ? left : right 被使用 >1 次。另外,请注意,无论在何处使用它,它都不会产生不同的东西,因此不需要重复调​​用。因此,为了避免这种情况,您可以简单地使用一个变量来存储比较的结果,然后随时随地调用该变量。 我不认为这个功能真的有效,虽然我不清楚预期的用途是什么。我的猜测是您的意图是 max2 保存结果,因为 max1 和函数的返回值似乎都是向量的最大值。 (使用全局变量是糟糕的设计,因为这意味着您只能在程序中调用该函数一次,除非您知道每次都重置它们。) 【参考方案1】:

if 在递归调用之前的时间复杂度方面并不是一个重要的贡献者。给定您的算法,最重要的是使用递归完成的数组拆分对时间复杂度的贡献。对您的算法进行试运行可以让您看到您的算法将遵循以下递归方程:T(n) = 2T(n/2) + θ(1)。请注意,此处的 θ(1) 表示您在 2 次递归函数调用之后编写的指令所消耗的恒定时间单位。这个 θ(1) 将与否相同。在递归调用之后,指令的数量是不变的。如果您使用一个运行时间取决于输入数组长度的循环,那么 θ(n) 将代替 θ(1) 出现。

那么,θ(1) 和 θ(n) 如何影响算法的复杂性?可以通过在递归方程上使用旧的 Master's Method 来简单地确定它。

对于 θ(1),您的等式将是:T(n) = 2T(n/2) + θ(1) & 对于 θ(n),它将变为 T(n) = 2T(n/2) + θ(n)。 在对这两种情况应用 Master's Theorem 之后,您将得到最终的时间复杂度,即第一个的 θ(log n) 和第二个的 θ(n [log n])。所以,这是您需要记住的主要区别。

【讨论】:

感谢您对此以及有关编译器计算负载的建议,我不知道。

以上是关于使用分而治之的数组的第二大元素的主要内容,如果未能解决你的问题,请参考以下文章

使用C使用分而治之查找数组中的多数元素

SIGABRT(信号 6)在使用分而治之的数组中查找多数元素时出错

分而治之以找到二维数组中两个有序元素之间的最大差异

如何在未排序数组的情况下找到未排序数组中的第k个最小整数?

如何使用分而治之以及如果一个子阵列占多数,组合阵列占多数以找到多数元素的事实?

给定已排序的数组,如果数组 A 包含元素 A[i] 使得 A[i] = i (递归和分而治之),则返回索引 i