我正在从代码强制中解决problem。根据{{3}},以下代码的复杂性应为O(n)。
for(int i = n - 1; i >= 0; --i) {
r[i] = i + 1;
while (r[i] < n && height[i] > height[r[i]])
r[i] = r[r[i]];
if (r[i] < n && height[i] == height[r[i]])
r[i] = r[r[i]];
}
此处,height[i]
是i
- 山的高度,r[i]
是第一个右山的位置,高于height[i]
,{{1在高度数组的其他值中总是最大的。
我的问题是,我们如何保证代码的复杂性为O(n),尽管内部while循环是?
在内部while循环中,代码更新height[0]
值,直到r[i]
&gt; height[i]
。并且更新的数量取决于高度数组。例如,按非递减顺序排序的高度数组的更新次数将不同于按非递增次序排序的高度数组的更新次数。 (在这两种情况下,我们将对除height[r[i]]
之外的数组进行排序,因为在这个问题中height[0]
应该总是最大的)。
有没有什么方法可以分析这样的输入数据变化的算法?摊销分析将是答案之一吗?
PS。我想更多地澄清我的问题,我们要在循环中设置数组r []。那怎么样?如果数组height[0]
和height = {5,4,1,2,3}
,(i=1
,r[2]=3
因为2是第一个大于1的值,而3是第一个大于2的值)我们要比较4和1,因为4> 1,我们一直试图比较4和2(= r[3]=4
),4和3(= height[r[2]]
)。在这种情况下,我们必须比较4次来设置r [1]。比较次数与height[r[3]]
时不同。我们还能保证代码的复杂性为O(n)吗?如果我错过了什么,请告诉我。谢谢。
答案 0 :(得分:0)
我用简单的例子尝试了上面提到的算法,但似乎没什么变化,我错过了什么?
示例:强>
n = 5
height = { 2, 4, 6, 8, 10 }
r = { 1, 2, 3, 4, 5 }
---- i:4 ----
r[4] < 5 ?
---- i:3 ----
8 > 10 ?
8 = 10 ?
---- i:2 ----
6 > 8 ?
6 = 8 ?
---- i:1 ----
4 > 6 ?
4 = 6 ?
---- i:0 ----
2 > 4 ?
2 = 4 ?
-------------
height = { 2, 4, 6, 8, 10 }
r = { 1, 2, 3, 4, 5 }
答案 1 :(得分:0)
你的算法(我不知道它是否会解决你的问题)实际上是O(n),即使有一个内循环,但在大多数情况下,由于给定条件,内循环不会执行。因此,在最坏的情况下,它将像2n
时间一样运行,即O(n)。
您可以使用这样的方法测试此假设,其中yourMethod
将返回执行内循环的时间:
int arr[] = {1, 2, 3, 4, 5};
do {
int count = yourMethod(arr, 5);
}while(next_permutation(arr, arr+5));
通过这种方式,您可以检查最坏情况,平均情况等。