簡體   English   中英

找到算法的 T(n)

[英]Finding the T(n) of An Algorithm

好的,所以當我的教授在課堂上復習時,它看起來很簡單,但是當我做作業時,我變得糊塗了。 這是一個家庭作業的例子。

for (int i = 0; i < n; i++)    // I know this runs at T(n)
 for (int j = n - 1; j >= i; j--)
 cout << i << " " << j << endl; 

這是我理解的一個例子

for(int i=0; i<n-1; i++) {
  for(int j=i+1; j<n; j++) {
    1 Simple statement
   }

對於那個例子,我只是插入了 0、1 和 2。對於 0,它運行 n-1,1 運行 n-2 和 2 n-3。 所以我認為對於作業示例,如果我插入 0,它將運行 n+1,因為 j 必須大於或等於 i,即 0。如果它不明顯,我很困惑。 如果有人能告訴我如何解決它,那會讓我開心。 謝謝你們。

讓我們深入研究這個函數。 讓我們選擇一些數字。

說,n = 5

所以我們的代碼看起來像這樣(神奇的偽代碼使用了 INCLUSIVE 循環,並不是說它太重要了)

(1)for i = 0 to 4
  (2)for j = 4 to i
     (3)print i j
  next
next

所以這是一個偏好問題,但通常假設循環每次執行(比較和增量)花費 1 個簡單語句。 所以我們假設語句 (1) 和 (2) 的成本為 2。語句 (3) 的成本為 1。

現在確定T(n)。

我們for i = 0 to 4外循環正好運行了 n 次。 我們的內部循環for j = 4 to i . . 我們將在那里挖掘一分鍾。

對於我們的 n = 5 示例,循環 (2) 將像這樣執行

j = 4; i = 0;  j = 4; i = 1;  j = 4; i = 2;  j = 4; i = 3  j = 4; i = 4;
j = 3; i = 0;  j = 3; i = 1;  j = 3; i = 2;  j = 3; i = 3;
j = 2; i = 0;  j = 2; i = 1;  j = 2; i = 2;
j = 1; i = 0;  j = 1; i = 1;
j = 0; i = 0; 

所以它形成了這種金字塔形狀,每次我們減少 1 次迭代。 這個特定的例子運行了 5 + 4 + 3 + 2 + 1 = 15 次。

我們可以把它寫成 SUM(i; i = 0 to n)。

我們從預計算中知道:= (1/2)(n)(n+1)。

並且 (3) 將執行與該內部循環完全相同的次數,因為它是唯一的語句。 所以我們的總運行時間將是。 . . 成本(1) + 成本(2) + 成本(3) (2)(n) + 2(1/2)(n)(n+1) + (1/2)(n)(n+1)

我們可以把它清理干凈

(3/2)(n)(n+1) + 2n = T(n)。

也就是說,這假設循環成本為 2,語句成本為 1。說循環成本為 0,語句成本為 1 通常更有意義。如果是這種情況,T(n) = (1/2)(n)(n +1)。

鑒於 T(n),我們知道 T(n) 是 O(n^2)。

希望這可以幫助!

這並不難。

單循環的 3 個示例:

for (int i = 0; i < n; i++)
for(int i = 0; i < n-1; i++)
for(int i = 2; i < n-1; i++)

第一個循環執行它的內容n次( i=0,1,2,3,...,n-1 )。
同理,第二個循環只是n-1次。
第三個是n-3因為它不是從 0 開始,而是從 2 開始
(如果n小於 3,即n-3<0 ,它根本不會執行)

在嵌套循環中

for(int i = 0; i < n-1; i++) {
  for(int j = 0; j < n; j++) {
    //something
  }
}  

對於外循環的每次傳遞,執行整個內循環,即。 您可以將兩個單循環計數相乘以獲得“某事”的總執行頻率。 在這里,它是(n-1) * n = n^2 - n

如果內循環依賴於外循環的值,它會變得有點復雜:

for(int i = 0; i < n-1; i++) {
  for(int j = i+1; j < n; j++) {
    //something
  }
}  

單獨的內部循環是n - (i+1)次,外部循環是n - (i+1) n-1次(其中 i 從 0 到n-2 )。
雖然有“適當”的方法來計算這個,但有點邏輯思維通常更容易,就像你已經做的那樣:

i-value => inner-loop-time
0 => n-1
1 => n-2
...
n-2 => n - (n-2+1) = 1  

所以你需要總和1+2+3+...+(n-1)
為了計算從 1 到 x 的總和,以下公式有幫助:

sum[1...x] = x*(x+1)/2  

所以,從 1 到n-1的總和是

sum[1...n-1] = (n-1)*(n-1+1)/2 = (n^2 - n)/2  

這就是上述循環的解決方案(您的第二個代碼)。

關於第一個代碼:
外環: n
內循環:從n-1i包含,或者從 i 到<=n-1的另一種方式,
或者從i<n ,那是ni

i >= innerloop
0 n
1 n-1
2 n-2
...
n-1 1

...從 1 到 n 的總和是(n^2 + n)/2

調查問題的一種簡單方法是對其進行建模並查看結果數據。

在您的情況下,問題是:根據外循環變量的值,內循環進行了多少次迭代?

let n = 10 in [0..n-1] |> List.map (fun x -> x,n-1-x);;

上面的 1 行是顯示發生了什么的模型。 如果您現在查看結果輸出,您會很快注意到一些事情......

val it : (int * int) list = [(0, 9); (1, 8); (2, 7); (3, 6); (4, 5); (5, 4); (6, 3); (7, 2); (8, 1); (9, 0)]

你注意到了什么? 對於給定的 N,您運行外循環 N 次 - 這是微不足道的。 現在我們需要總結第二個數字,我們有解決方案:

sum(N-1..0) = sum(N-1..1) = N * (N-1) / 2

所以cout調用的總數是 N * (N-1) / 2。

實現相同目標的另一種簡單方法是稍微修改您的函數:

int count(int n) {
   int c = 0;
   <outer for loop>
       <inner for loop>
           c++;
   return c;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM