题目要求:
- 01 有以下用Java语言描述的算法,说明其功能并计算复杂度,注意:时间结束后的回答无效
double fun(double y,double x,int n) { y=x; while (n>1) { y=y*x; n--; } return y; }
- 02
- 设 n 为正整数, 给出下列 3 个算法关于问题规模 n 的时间复杂度。
(1) 算法 1
void fun1(int n) { i=1,k=100; while (i<=n) { k=k+1; i+=2; } }
题目答案:
-
01 O(n)
-
功能为:
-
在n大于1的时候,计算x的n的次方。
while (n>1) { y=y*x; n--; }
-
若n小于一,则返回x(因为y=x)
return y;
-
02
-
(1)O(n)
-
(2)O(n²)
-
(3)O(根号n)
答题思路:
- 首先我参考了一下博客
- 在看完这篇博客后,我一开始对于算法复杂度的理解是这样的:
- 1.有一个循环算一个n,有两个循环就n*n,算法复杂度就是看多少个n相乘就是O(n)的多少次方。
- 2.有一个if的时候,操作次数就除以2。
- 但是我发现,我的想法好像和链接里面不是特别的一样?
- 比如:
- 1.为什么示例代码(1)中没有循环只有一个if函数算法复杂度也是O(n)?
- 2.为什么示例代码(3)中的基本步骤执行的数量是n*(n-1)/2?
- 首先回答第一个问题,我们观察一下示例代码:
decimal Factorial(int n) { if (n == 0) return 1; else return n * Factorial(n - 1); }
- 我们可以看出来,这是一个计算阶乘的代码,那么计算阶乘要计算几次呢?(n次)所以这个代码的基本步骤执行的数量为 n,算法复杂度我们也可以轻易得出:是O(n)。
- 第二个问题,示例代码如下:
long FindInversions(int[] array) { long inversions = 0; for (int i = 0; i < array.Length; i++) for (int j = i + 1; j < array.Length; j++) if (array[i] > array[j]) inversions++; return inversions; }
- 这个代码的基本步骤执行的数量为n(n-1)/2,但我当时以为是nn/2。
- 那么问题出在哪里呢?
- 因为在代码
if (array[i] > array[j])
中,给出的是两个未知量的比较,所以我们要除以2。与另一个代码if (array[i] > max) { max = array[i]; }
不同的是,这里我们需要考虑最坏情况,也就是这个代码要比较n次才能得到最大值。所以这个示例代码(2)的算法复杂度为O(n)。 - 至于为什么是n*(n-1)那是因为每当
for (int i = 0; i < array.Length; i++)
循环一次的时候,for (int j = i + 1; j < array.Length; j++)
要循环n-1次。 - 所以最终这个代码的算法复杂度为O(n^2)。
- 那么当我们理清思路的时候,我们也就能得出题目的答案。
- 01的解题思路为:
- 在while循环中,我们看到它给定的规模是n,算法基本执行的数量为n,所以算法复杂度为O(n)。
- 02的解题思路为:
- (1):
- 给定规模n,则基本步骤的执行数量为n,所以算法复杂度为O(n)
- (2):
- 给定规模n,则基本步骤的执行数量为(n-1)*(n-1)/2,所以算法复杂度为O(n²)
- (3):
- 给定规模n,优化后算法复杂度为O(根号n)。