【问题标题】:Time complexity of insertion sort on k-shifted arrayk-shifted数组插入排序的时间复杂度
【发布时间】:2022-11-23 20:42:19
【问题描述】:

这个问题在我的算法课程作业中被问到。经过大量搜索(我无法在互联网上找到解决方案),我想我找到了解决方案并决定与社区分享我的知识,以防其他人可能会遇到这种问题。顺便说一句,截止日期已经结束,所以我可以安全地分享。

首先的问题是: 您首先有一个 n 大小的排序数组。比方说n=10,数组是[1,2,3,4,5,6,7,8,9,10]。然后循环右移k。让我们说k=3。现在数组是[8,9,10,1,2,3,4,5,6,7]。如果您在此数组上应用插入排序,则根据 nk 找到该特定条件的时间复杂度公式。

【问题讨论】:

  • 你是不是刚问了一个问题就马上自己回答了?你在测试坎宁安定律之类的吗?
  • @GeertPt 提出和自我回答问题是完全可以的,也是允许的。
  • @GeertPt 技术上我没有问问题,分享了一个解决方案
  • @Baran 好的,很公平!
  • 但 Stack Overflow 上的问题仍应表述为问题,而不是博客。

标签: java algorithm sorting insertion-sort


【解决方案1】:

首先是插入排序:

static void insertionSort(int[] array) {
    for (int i = 1; i < array.length; i++) {
        int key = array[i];
        int j = i - 1;

        while (j >= 0 && array[j] > key) {
            array[j + 1] = array[j];
            j--;           
        }

        array[j + 1] = key;
    }
}

时间复杂度主要取决于以下几行,因为这是完成比较和交换操作的地方。

while (j >= 0 && array[j] > key) {
    array[j + 1] = array[j];
    j--;
    swapCount++;
}

拿一张纸,为每个 j 值绘制一个交换表。

最终,你会明白算法进入 while 循环 (n-k) 次,每当进入时,它都会进行交换操作 k 次。所以,时间复杂度是(n-k)*k

让我们证明一下。

将交换计数器变量放入算法中。

static int insertionSort(int[] array) {
    int swapCount = 0;

    for (int i = 1; i < array.length; i++) {
        int key = array[i];
        int j = i - 1;
        while (j >= 0 && array[j] > key) {
            array[j + 1] = array[j];
            j--;
            swapCount++;
        }

        array[j + 1] = key;
    }

    return swapCount;
}

现在,让我们在问题中描述的数组上尝试一下。

public class App {
    public static void main(String[] args) throws Exception {
        int[] baseArray = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        int n = baseArray.length;
        int k = 3;

        // Shift base array by k
        int[] shiftedArray = shiftArray(baseArray, k);

        // Calculate how many swaps done by the insertion sort
        int swapCount = InsertionSort.insertionSort(shiftedArray);

        // Theroitical value is calculated by using the formula (n-k)*k
        int timeComplexityTheoritical = (n - k) * k;

        System.out.print("Theoritical Time Complexity based on formula: " + timeComplexityTheoritical);

        System.out.print(" - Swap Count: " + swapCount);

        System.out.print(" - Is formula correct:" + (timeComplexityTheoritical == swapCount) + "
");
    }

    // Shift array to the right circularly by k positions
    static int[] shiftArray(int[] array, int k) {
        int[] resultArray = array.clone();

        int temp, previous;
        for (int i = 0; i < k; i++) {
            previous = resultArray[array.length - 1];
            for (int j = 0; j < resultArray.length; j++) {
                temp = resultArray[j];
                resultArray[j] = previous;
                previous = temp;
            }
        }

        return resultArray;
    }

    static class InsertionSort {

        static int insertionSort(int[] array) {
            int swapCount = 0;

            for (int i = 1; i < array.length; i++) {
                int key = array[i];
                int j = i - 1;
                while (j >= 0 && array[j] > key) {
                    array[j + 1] = array[j];
                    j--;
                    swapCount++;
                }

                array[j + 1] = key;
            }

            return swapCount;
        }
    }
}

输出:

基于公式的理论时间复杂度:21 - 交换计数:21 - Is 公式正确:正确

我试过大小为 2^16 的数组并将其移动 2^16-1 次,每次公式都是正确的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-30
    • 2013-11-18
    • 2021-03-05
    • 2011-09-01
    • 2013-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多