[英]Big o of insertion sort algorithm: iterative and recursive
這里我有兩個插入排序算法。 我很難找到這兩種形式的插入排序的大O. 我有一個迭代形式和一個遞歸形式。 我錯誤地說迭代形式是n ^ 2並且遞歸形式是n ^ 2。 如果我錯了,他們是什么,為什么? 你是怎么回答這個問題的?
public void iterativeSort(int[] list) {
start = System.currentTimeMillis();
for (int i = 1; i < list.length; i++) {
count++;
int temp = list[i];
int j;
for (j = i - 1; j >= 0 && temp < list[j]; j--) {
list[j + 1] = list[j];
}
list[j + 1] = temp;
finish += System.currentTimeMillis() - start;
}
}
public static void recursiveSort(int array[], int n, int j) {
finish += System.currentTimeMillis() - start;
start = System.currentTimeMillis();
if (j < n) {
int i;
count++;
int temp = array[j];
for (i = j; i > 0 && array[i - 1] > temp; i--) {
array[i] = array[i - 1];
}
array[i] = temp;
recursiveSort(array, n, j + 1);
}
}
是的,你是對的,兩個實現都需要O(n^2)
時間。 您不可能通過從遞歸實現切換到迭代實現來減少算法的運行時間,反之亦然。 這不抱空間使用率雖然。
如何確定運行時間為O(n^2)
。 迭代解決方案更容易,更明顯。 通常,當您嵌套for
-loops而沒有任何特定的中斷條件並且您正在運行一小部分線性元素時,運行時間是二次的。 讓我們進一步分析吧。 for (int i = 1; i < list.length; i++)
in for (int i = 1; i < list.length; i++)
的條件for (int i = 1; i < list.length; i++)
多少次為true
? 答案是n-1
,因為你從第二個元素開始直到結束。 例如,如果n=5
,則對於i = 1, 2, 3, 4
(由於基於0的索引),條件將為true
,恰好為n-1
次,在此示例中表示為4.現在將多少次內循環條件評估為true
? 在第一次運行時,它將執行一次,因為i = 1
且j = 0
並且在一次迭代之后j
將為-1
,這將破壞該條件。 在第二次迭代中,它將被執行兩次,在第三次三次等,最多n - 1
次。 所以我們基本上得到的是1 + 2 + 3 + ... + (n - 1)
,你很容易證明它等於(n-1)n/2)
。 由於你在big-O中刪除常量,因此運行時間為O(n^2)
。
現在,由於遞歸,對第二個實現的分析可能看起來更復雜,但實際上並沒有太大的不同。 內循環的邏輯for (i = j; i > 0 && array[i - 1] > temp; i--)
幾乎相同,因為它執行一次,當j = 1
,兩次執行j = 2
等。我們將遞歸調用該方法多少次? 再次n - 1
次,因為第一次調用是j = 1
,因此j < n
(假設n很大),然后recursiveSort(array, n, j + 1);
。 現在j = 2
再次小於n
,所以我們將遞歸地調用函數直到j == n
,所以恰好n - 1
次。 假設內循環嵌套在O(n)
,我們得到相同數量的迭代,即1 + 2 + 3 + ... + ( n-1 )
,再次導致O(n^2)
。
因此我們非正式地證明了這兩種算法具有相同的漸近運行時間。 在這種情況下,我們可以認為它們相同嗎 不 。 這是因為每個遞歸調用都會在堆棧上保留額外的空間,這意味着遞歸解決方案需要O(n)
空間,而迭代解決方案需要O(1)
。 在這個意義上,我們可以說迭代解決方案更好,通常是這種情況,但遞歸的解決方案可能更具可讀性(這不是這里的情況)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.