从算法中获取时间复杂度

时间:2017-09-24 06:18:26

标签: java algorithm loops for-loop code-analysis

我正在尝试了解算法的时间复杂度。我的教授已将它推到了Big O之外,并希望我们能够将算法推导出数学函数。我很难概念化这是如何完成的,并且正在寻求帮助。在我的课堂笔记中,提供了一种选择排序算法(如下面的代码所示)。这些注释提出了以下问题:"导出函数f(n),该函数对应于在最坏的情况下修改 minIndex或任何nums位置的总次数。 现在笔记告诉我答案是 f(n)= 1 / 2n ^ 2 + 5 / 2n + 3 。我想知道是否有人能解释这是怎么发生的。

我的教授告诉我们要计算内循环中的操作并努力解决问题。所以我相信在最坏的情况下,在内部循环中if语句总是执行,这意味着我们运行循环ni-1次,我通过取n(for循环必须小于的边界并减去)得到这些值它由起始条件(i + 1)。然后我看外环,我看到它从i到达n-1,所以它可以写成(n-1)-i或就像内部循环,ni-1。进一步看,外循环有三个修改,所以得到(ni-1)+3(我可以把它写成(n-i + 2)吗?

内循环最坏情况下的修改次数: N-1-1

外循环最坏情况下的修改次数: (N-1-1)3

现在我想知道你如何计算完成的两个不同的修改并成为f(n)= 1 / 2n ^ 2 + 5 / 2n + 3.

public static void selectionSort(int[] nums) {

        int n = nums.length;
        int minIndex;

        for(int i = 0; i < n-1; i++) {
            //find the index of themin number.
            minIndex = i;

            for(int j = i+1; j < n; j++) {
                if(nums[j] < nums[minIndex]) {
                    minIndex = j;
                }
                int temp = nums[i];
                nums[i] = nums[minIndex];
                nums[minIndex] = temp;
            }
        }
}

1 个答案:

答案 0 :(得分:0)

外循环运行多少次?
n - 1

对于外循环的每次迭代,内循环运行了多少次?
n - 1次到1次,随着外循环的进展,平均来说: ((n - 1) + 1) / 2 = n / 2次。

那么,内循环总计中运行多少次?
(n - 1) * (n / 2) = n^2 / 2 - n / 2

minIndex修改了多少次?
每个外环一次+每个内环一次:
(n - 1) + (n^2 / 2 - n / 2) = n^2 / 2 + n / 2 - 1次。

nums修改的位置的次数是多少? 每个内循环两次:
2 * (n^2 / 2 - n / 2) = n^2 - n次。

总数 修改的数量是什么? (n^2 / 2 + n / 2 - 1) + (n^2 - n) = (3*n^2 - n) / 2 - 11½n² - ½n - 1

这和你说的笔记不一样,所以我们来证明一下。

首先,我们添加调试打印,即打印任何修改,包括修改编号。

public static void selectionSort(int[] nums) {
                                              int mod = 0;
    int n = nums.length;
    int minIndex;

    for(int i = 0; i < n-1; i++) {
        //find the index of themin number.
        minIndex = i;                         System.out.printf("%2d: minIndex = %d%n", ++mod, i);

        for(int j = i+1; j < n; j++) {
            if(nums[j] < nums[minIndex]) {
                minIndex = j;                 System.out.printf("%2d: minIndex = %d%n", ++mod, j);
            }
            int temp = nums[i];
            nums[i] = nums[minIndex];         System.out.printf("%2d: nums[%d] = %d%n", ++mod, i, nums[minIndex]);
            nums[minIndex] = temp;            System.out.printf("%2d: nums[%d] = %d%n", ++mod, minIndex, temp);
        }
    }
}

最坏的情况是对降序数字进行排序,所以让我们尝试3个数字:

int[] nums = { 3, 2, 1 };
selectionSort(nums);
System.out.println(Arrays.toString(nums));

我们希望(3*n^2 - n) / 2 - 1 = (3*3^2 - 3) / 2 - 1 = 24 / 2 - 1 = 11次修改。

 1: minIndex = 0
 2: minIndex = 1
 3: nums[0] = 2
 4: nums[1] = 3
 5: minIndex = 2
 6: nums[0] = 1
 7: nums[2] = 2
 8: minIndex = 1
 9: minIndex = 2
10: nums[1] = 2
11: nums[2] = 3
[1, 2, 3]

是的,11次修改。

让我们试试9:

int[] nums = { 9, 8, 7, 6, 5, 4, 3, 2, 1 };

(3*n^2 - n) / 2 - 1 = (3*9^2 - 9) / 2 - 1 = 234 / 2 - 1 = 116次修改。

  1: minIndex = 0
  2: minIndex = 1
  3: nums[0] = 8
  4: nums[1] = 9
  5: minIndex = 2
  6: nums[0] = 7
      . . .
111: nums[6] = 7
112: nums[8] = 8
113: minIndex = 7
114: minIndex = 8
115: nums[7] = 8
116: nums[8] = 9
[1, 2, 3, 4, 5, 6, 7, 8, 9]

是的,116修改。

通过经验证据验证的公式:
f(n) = (3*n^2 - n) / 2 - 1