【问题标题】:Explanation of best case of Bubble Sort being O(n) and not O(n^2)?冒泡排序的最佳情况是 O(n) 而不是 O(n^2) 的解释?
【发布时间】:2019-07-28 23:14:56
【问题描述】:

给定一个冒泡排序算法

for (int i = 0; i < A.length - 1; i++)
            for (int j = 0; j < A.length - i - 1; j++)
                if (A[j] > A[j + 1]) {
                    int temp = A[j];
                    A[j] = A[j + 1];
                    A[j + 1] = temp;
                }

在给定的数组已经排序的情况下,内部循环中的 if 语句将始终为 false 打破内部 for 循环并递增 j 直到达到 A.length-i-1。当达到A.length-i-1 时,i 增加。这个过程循环直到i 达到A.length-1

我的困惑:

如果两个嵌套循环都迭代到各自的上限,尽管没有进行交换,但最佳情况下时间复杂度是否仍为 O(n^2)?谁能简单地向我解释一下为什么会是 O(n)

【问题讨论】:

标签: java time time-complexity


【解决方案1】:

如果程序按原样,是的,在最佳情况下仍需要 O(n^2)。但是你可以增强这个程序。

在您第一次通过时,您会看到没有发生任何交换。您可以保留一个标志,以检查是否在通行证期间没有发生交换,您不需要进一步通行证。

在这种情况下,你只会做一次,时间复杂度将是 O(n)

示例程序(结构可能更好):

        boolean previousIterationSwap = false;
        final int[] A = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        for (int i = 0; i < A.length - 1; i++) {
            // After the first iteration check if previous iteration had any
            // swap
            if (i > 0 && !previousIterationSwap) {
                break;
            }
            for (int j = 0; j < A.length - i - 1; j++) {
                if (A[j] > A[j + 1]) {
                    previousIterationSwap = true;
                    final int temp = A[j];
                    A[j] = A[j + 1];
                    A[j + 1] = temp;
                } else {
                    previousIterationSwap = false;
                }
            }
        }

【讨论】:

  • 只是一个关于这个解决方案的简单问题。如果在第一遍过程中不需要交换,那么它会打破内部 for 循环并迭代外部 for 循环一次并重新启动,对吗?
  • 是的,我还添加了一个快速解决方案。
【解决方案2】:

考虑以下代码:

int[] bubbleSort(int[] arrayToBeSorted){
        int n = arrayToBeSorted.length; // length of array
        int temp = 0; // to store value temporarily
        int flag =0; // to check if given array already sorted or not
        for (int i=0;i<n-1;i++){
            for (int j=0;j<n-i-1;j++){
                if(arrayToBeSorted[j] > arrayToBeSorted[j+1]){
                    flag = 1;
                    temp = arrayToBeSorted[j];
                    arrayToBeSorted[j] = arrayToBeSorted[j+1];
                    arrayToBeSorted[j+1] = temp;
                }
            }
            //checking if array is sorted already or not
            if (flag ==0){
                System.out.println("Already sorted so time complexity is only O(N)");
                break;
            }
        }
        return arrayToBeSorted;
    }

如果你在上面的代码中有一个未排序的数组,那么嵌套的 for 循环将被执行,直到给定的数组完全排序。因此它将花费n*n -&gt; O(n*n) 时间复杂度。

但是如果你提供一个已经排序好的数组,你可以在上面的代码中看到,当 i=0 时,嵌套的 j 循环会被执行 n-i-1 次,但是 if 块里面的代码不会被执行。

for (int j=0;j<n-i-1;j++){
                if(arrayToBeSorted[j] > arrayToBeSorted[j+1]){
                    flag = 1;
                    temp = arrayToBeSorted[j];
                    arrayToBeSorted[j] = arrayToBeSorted[j+1];
                    arrayToBeSorted[j+1] = temp;
                }
            }

这意味着您的数组已经排序。所以标志将保持原样为0。 因此,在进入第二个增量即 i=1 之前,

您的循环将停止,因此您可以保存另一个 n 迭代。 因此,循环只执行 n 次而不是 n*n 次。

如果数组已经排序,这将中断你的循环以进一步执行

     if (flag ==0){
                System.out.println("Already sorted so time complexity is only O(N)");
                break;
            }

【讨论】:

    猜你喜欢
    • 2012-07-13
    • 2012-09-12
    • 2022-01-11
    • 2023-04-01
    • 2020-09-26
    • 1970-01-01
    • 2021-08-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多