Document 7915043
Download
Report
Transcript Document 7915043
Data Structures
การวิเคราะห์ความเร็ วของโค้ด
Algorithm คือ คาสัง่ และขั้นตอนต่างๆที่ไว้ทาเพื่อ
แก้ปัญหา
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
1
Introduction
ทำไมต้องเรียนโครงสร้ำงข้อมูล
เข้ าใจ code ต่ าง ๆ ได้ ง่าย
เลือกใช้ โครงสร้ างข้ อมูลได้ อย่ างถูกต้ องเหมาะสม
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
2
ตัวอย่างเช่น เราเลือกเก็บจานวนเต็ม 5 จานวน (1
ถึง 5 ) ลงในโครงสร้ างข้ อมูล
Linked ist
P
1
2
3
4
5
P
Tree (Binary
Search Tree)
2
1
4
3
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
5
3
การเลือกเก็บข้ อมูล (ต่ อ)
5
Heap
4
2
5/27/2016
3
1
ถ้าต้องการข้อมูลที่มากที่สุด
ก็ตอ้ งเลือกโครงสร้างการเก็บ
ที่ช่วยให้หาข้อมูลนั้นได้เร็ ว
ที่สุด ในที่น้ ี Heap จะ
เหมาะที่สุด
อ. ดร. วิษณุ โคตรจรัส
4
กำรคำนวณควำมเร็วของโปรแกรม
Big O
ถ้า
T ( N ) c( f ( N ))
โดยมี c กับ N0 เป็ นค่าคงที่และ N>=N0
นี่คือการบอกว่า T(N) เติบโตอย่างไร
T ( N ) ( f ( N ))
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
5
ตัวอย่ างการคานวณ BIG O
ถ้า T(N) = 339N และ f(N) = N*N
ถ้าให้ N0 = 339 และ C = 1
เราสามารถจะเห็นได้ทน
ั ทีวา่
339N0 <= 1*(N0*N0)
T ( N 0) c( f ( N 0))
T ( N ) ( f ( N )) ( N )
2
แต่มีคาตอบอื่นด้วย ->
5/27/2016
T(N) <= 1*(340N) ก็ถูกเหมือนกัน
อ. ดร. วิษณุ โคตรจรัส
6
ตัวอย่ างการคานวณ BIG O (ต่ อ)
ดังนั้น T(N)=O(N) ก็ถูกเหมือนกัน แล้วจะตอบอะไรกันแน่
ให้ตอบเป็ นค่าที่นอ้ ยที่สุด เพราะค่าที่นอ้ ยที่สุด คือค่าที่เราเอามาใช้
จริ งๆในการคิดความเร็ วของ โปรแกรม ฉะนั้น O(N) เป็ นคาตอบ
แล้ว O(N) มันเกี่ยวอะไรกับการหาความเร็ วในการ execute ของ
code ขอให้เราดูตวั อย่างต่อไป
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
7
หาความเร็วของโค้ ดต่ อไปนี้ แบบละเอียด
sigmaOfSquare(int n) // calculate
{
1:
2:
3:
4:
5:
}
5/27/2016
1 unit (declare only)
1 unit
int tempSum;
1 unit (assignment)
tempSum = 0;
n+1 unit
n unit
for (int i=1;i<n;i++)
คูณ บวก และ
tempSum += i*i;
assignment อย่างละ n
return tempSum;
จึง = 3n unit
1 unit (return)
รวมได้ 5n+5 unit
อ. ดร. วิษณุ โคตรจรัส
8
หาความเร็วแบบละเอียดไม่ ไหวหรอก
5/27/2016
แต่วา่ โปรแกรมแค่น้ ียงั เสี ยเวลาในการกะ running time ขนาดนี้ ดังนั้น
โปรแกรมใหญ่ ๆ ยิง่ ไม่ตอ้ งพูดถึง ดังนั้น ถ้าจะคานวณ running time
ของโปรแกรมให้รวดเร็ วเราจาเป็ นต้องใช้การประมาณอย่างคร่ าว ๆ
กว่านี้ นัน่ คือต้องใช้ Big O นัน่ เอง
จากหน้าที่แล้ว เรากะได้จาก loop เวลาในการ run ส่ วนอื่นจะน้อย
มากเมื่อเทียบกับส่ วนที่เป็ น loop ซึ่งทาซ้ าไปเป็ น ผลคูณของ n ครั้ง
ฉะนั้น เมื่อคิดจากตัว loop โปรแกรมนี้ จะมีBig O = O(n)
ซึ่งเวลาจริ ง 5n+5 ก็เป็ น O(n) (จะเห็นว่า 5n+5<= 6n)
อ. ดร. วิษณุ โคตรจรัส
9
การหา BIG O จาก loop ต่ างๆ
For loop ค่า Big O คือ จานวนครั้งที่ loop ทาซ้ า
Nested loop
n รอบ
1:
2:
5/27/2016
for (i = 1; i <= n; i++)
n รอบ
for (j = 1; j <= n; j++)
statements;
Big O จะเป็ น O(n2)
อ. ดร. วิษณุ โคตรจรัส
10
การหา BIG O จาก loop ต่ างๆ (ต่ อ)
นิยามของการคิด Nested loop เป็ นดังนี้
ถ้า T1(N)=O(f(N)) และ T2(N)= O(g(N)) แล้ว
ละก็
T1(N)* T2(N)= O(f(N)*g(N))
จากตัวอย่างนั้น
f(n) = g(n) = n
จึงตอบเป็ น O(n2)
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
11
การหา BIG O จาก loop ต่ างๆ (ต่ อ 2)
Statement ที่เรียงต่ อกันเป็ นบรรทัด
1:
2:
3:
4:
5:
for (i = 0; i <= n; i++)
O(n)
statement1;
for (j = 0; j <= n; j++)
for (k = 0; k <= n; k++)
statement2;
O(n2)
เอาตัวมากสุ ดมาตอบ นัน่ คือ O(n2)
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
12
การหา BIG O จาก loop ต่ างๆ (ต่ อ 3)
นิยามของการหา running time จาก Statement ที่เรี ยงต่อกัน
ถ้า T1(N)=O(f(N)) และ T2(N)= O(g(N)) แล้ว
ละก็
T1(N)+
T2(N)= max(O(f(N),O(g(N)))
จากตัวอย่าง
f(n) = O(n), g(n) = O(n2)
จึงตอบเป็ น O(n2)
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
13
การหา BIG O จาก loop ต่ างๆ (ต่ อ 4)
ประโยคแบบมีเงื่อนไข
1:
if (condition)
2:
Statement1
3:
4:
O(f(n))
Else
Statement2
O(g(n))
เอาตัวมากสุ ดมาตอบ นัน่ คือ
max(O(f(n),O(g(n)))
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
14
การหา BIG O จาก recursion
1:mymethod (int n) {
2:
if (n == 1) {
3:
return 1;
4:
} else {
5:
return 2*mymethod(n – 1) + 1;
6:
}
7:}
n ครั้ง, big O = O(n)
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
15
Maximum Subsequence Sum,
ตัวอย่ างการเลือก code ที่ให้ Big O ดีทสี่ ุ ด
Maximum Subsequence Sum คือ
ถ้ามีจานวนเต็ม A1,A2,
j
… ถึง An
Ak ที่มีค่า
Maximum Subsequence Sum คือค่า
k i
มากที่สุด (คือส่ วนที่ติดกัน ที่ให้ผลบวกมากที่สุด)
ติดกัน
ตัวอย่างเช่น -2, 11, -6, 16, -5, 7
ผลรวมของ 11, -6, 16 คือ 21 (ดูมาก ตามสัญชาติญาณ) แต่ที่มาก
ที่สุด ก็คือ จากช่วง 11, -6, 16, -5, 7 ซึ่งรวมแล้วได้ 23 นี่แหละคือ
Maximum Subsequence Sum
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
16
วิธีการแก้ max sub sum แบบที่ 1
1: int maxSubSum01 ( int [] a) {
2:
int maxSum = 0;
index แรก
3:
for (int i = 0; i < a.length; i++) {
index สุ ดท้าย
4:
for (int j = i; j < a.length; j++) {
5:
int theSum = 0;
6:
for (int k = i; k <= j; k++) { บวกตั้งแต่แรกถึง
7:
theSum += a[k];
สุ ดท้าย
8:
}
9:
if (theSum > maxSum) {
เลือกเก็บผลที่
10:
maxSum = theSum;
มากที่สุด
11:
}
12:
}
13:
return maxSum;
14:
}
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
17
15: }
วิธีการแก้ max sub sum แบบที่ 1 (ต่ อ)
วิธีที่ 1 นี้มี big O =
ดูจากโปรแกรม
แต่แค่น้ ี ยงั ไม่ดีพอ เพราะมีการคานวณที่ซ้ าซ้อนมาก
เกินไป
3
O(n )
ถ้าบวกจากตาแหน่ ง 0 ถึง2 ไปแล้ว ตอนที่บวกจากตาแหน่ งที่
0 ถึง 3 กลับต้องเริ่ มบวกใหม่หมด แทนที่จะใช้ผลจากการบวก
จากตาแหน่ง 0 ถึง2 ได้
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
18
วิธีการแก้ max sub sum แบบที่ 2
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
5/27/2016
int maxSubSum02 (int [] a) {
ตัวเริ่ ม
int maxSum = 0;
for (int i = 0; i < a.length; i++) {
int theSum = 0;
for (int j = i; j < a.length; j++) {
บวกจาก
theSum += a[j];
ตัวเริ่ มและ
if (theSum > maxSum) {
สะสมค่า
maxSum = theSum;
}
เรื่ อยๆ
}
BIG O = O(n2)
}
return maxSum;
}
อ. ดร. วิษณุ โคตรจรัส
19
วิธีการแก้ max sub sum แบบที่ 2 (ต่ อ)
-2
11
-6
4
เมื่อ i=0, j=0:
theSum = -2
เมื่อ i=0, j=1:
theSum = -2 + 11 = 9
maxSum กลายเป็ น 9
เมื่อ i=0, j=2:
theSum = 9 + (-6) = 3
maxSum ยังคงเป็ น 9
เมื่อ i=0, j=3:
theSum = 3 + 4
maxSum ยังคงเป็ น 9
5/27/2016
maxSum = 0
อ. ดร. วิษณุ โคตรจรัส
20
วิธีการแก้ max sub sum แบบที่ 3
ใช้ divide and conquer
คาตอบอาจจะอยูใ่ น
ครึ่ งซ้ายของการแบ่งปั ญหา หรื อ
ครึ่ งขวาของการแบ่งปั ญหา หรื อ
่ ้ งั สองข้าง (ต้องมีตวั สุ ดท้ายจากครึ่ งซ้ายและตัว
อยูท
แรกจากครึ่ งขวา)
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
21
วิธีการแก้ max sub sum แบบที่ 3 (ต่ อ)
1
-2
7
-6
Max sub sum ข้างนี้คือ 7
ของครึ่ งซ้ายที่มีตวั สุ ดท้าย (-6) คือ 1
2
8
-5
4
Max sub sum ข้างนี้คือ 10
ของครึ่ งขวาที่มีตวั แรก(2) คือ 10
Max sub sum ที่คาบเกี่ยวข้างซ้ายและขวา คือ 1 +10 = 11 นี่คือคาตอบ
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
22
วิธีการแก้ max sub sum แบบที่ 3 (ต่ อ 2)
1:int maxSumDivideConquer (int [] array, int leftindex, int
rightindex {
2: // ต้ องถือว่าขนาดของอาร์ เรย์หารสองลงตัวพอดีจะได้ แบ่งได้ เท่ากัน ไม่เช่นนันโปรแกรมจะยุ
้
่งยาก
3:
if (leftindex == rightindex) { // Base Case
T(n)
5:
if (array[leftindex] > 0 )
6:
return array[leftindex];
7:
else
8:
return 0; // maxSubSum มีค่าต่าสุดคือ 0 เท่านัน้
9:
}
T(n/2)
10: int centerindex = (leftindex + rightindex)/2;
12: int maxsumleft = maxSumDivideConquer(array,
T(n/2)
leftindex, centerindex);
13: int maxsumright = maxSumDivideConquer ( array,
centerindex + 1, right);
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
23
วิธีการแก้ max sub sum แบบที่ 3 (ต่ อ 3)
14:
15:
int maxlefthalfSum = 0, lefthalfSum = 0;
// เก็บผลรวมที่มากที่สดุ นับจากตัวสุดท้ ายของครึ่งซ้ ายลงไปถึงตัวแรก
16:
17:
18:
19:
20:
21:
for (int i = center; i >= leftindex; i--) {
lefthalfSum = lefthalfSum + array[i];
if (lefthalfSum > maxlefthalfSum) {
maxlefthalfSum = lefthalfSum;
}
}
O(n/2)
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
24
วิธีการแก้ max sub sum แบบที่ 3 (ต่ อ 4)
22: int maxrighthalfSum = 0, righthalfSum = 0;
23: // เก็บผลรวมที่มากที่สดุ นับจากตัวแรกของครึ่งขวาไปถึงตัวสุดท้ าย
24: for (int i = centerindex + 1; i <= rightindex; i++) {
25:
righthalfSum = righthalfSum + array [i];
26:
if (righthalfSum > maxrighthalfSum) {
27:
maxrighthalfSum = righthalfSum;
28:
}
29: }
O(n/2)
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
25
วิธีการแก้ max sub sum แบบที่ 3 (ต่ อ 5)
30: // จากนันหา
้ max ของทัง้ 3 กรณี คือ ของครึ่งซ้ าย, ของครึ่งขวา, และของที่อยู่
ทัง้ 2 ครึ่ง
31: return max3 (maxsumleft, maxsumright,
maxlefthalfSum + maxrighthalfSum)
}
ส่ วนนี้หา max จากสามตัว ใช้เวลาคงที่ เราไม่ตอ้ งสนใจ
ดังนั้น เวลารวมทั้งหมดจะเป็ น
T(n) = 2T(n/2) + 2O(n/2)
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
26
วิธีการแก้ max sub sum แบบที่ 3 (ต่ อ 6)
หลังจากได้ unit time มาแล้ว คราวนี้เอามาหา BIG O เลย
T(n) = 2T(n/2) + 2O(n/2)
= 2T(n/2) + O(n)
= 2T(n/2) + cn เพราะ O(n) <= c*n ตามนิยาม
เอา n หารตลอดจะได้
5/27/2016
n
T( )
T ( n)
2 c
n
n
2
อ. ดร. วิษณุ โคตรจรัส
(1)
27
วิธีการแก้ max sub sum แบบที่ 3 (ต่ อ 7)
เมื่อทาไปเรื่ อยๆ จะได้
n
n
T( ) T( )
2 4 c
n
n
2
4
n
n
T( ) T( )
4 8 c
n
n
4
8
.................
T (2) T (1)
c
2
1
5/27/2016
(2)
(3)
(X)
อ. ดร. วิษณุ โคตรจรัส
28
วิธีการแก้ max sub sum แบบที่ 3 (ต่ อ 8)
เมื่อเอา (1) + (2) + (3) +…..+ (x) จะได้
T (n) T (1)
c * log 2 (n)
n
1
เพราะว่าด้านซ้ายและขวาตัดกันได้เยอะ ส่ วน c ก็บวกกันได้เป็ น
จานวน log2 n ครั้งยังไงล่ะ
เอา n คูณหมด จะได้
T (n) n *T (1) c * n * log 2 (n)
และเพราะ T(1) เป็ นค่าคงที่ เราจึงรู ้ได้ทน
ั ทีวา่ T(n) มี Big O =
O(n log n)
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
29
วิธีการแก้ max sub sum แบบที่ 4
คือการเอาวิธีที่ 2 มาปรับปรุ ง โดยมีขอ้ สังเกตที่หนึ่ งว่า
ตัวแรกของ maximum subsequence sum จะเป็ นค่าลบไม่ได้
อย่างเช่น 3, -5, 1, 4, 7, -4
ค่า -5 จะเป็ นตัวแรกของ sequence ของคาตอบไม่ได้ แค่เราให้ตวั
แรกเป็ นเลขตัวต่อไป (ในที่น้ ีคือเลข 1) เราก็จะได้ค่ารวมมากขึ้น
แล้ว (อย่าลืมว่าเราใช้สมมติฐานว่า maximum subsequence sum
มีค่าน้อยที่สุดคือ 0)
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
30
วิธีการแก้ max sub sum แบบที่ 4 (ต่ อ)
ข้อสังเกตที่สองคือ
subsequence ที่มีผลรวมเป็ นลบ ไม่สามารถเป็ นส่ วนเริ่ มต้นของ
maximum subsequence sum ได้
่ ะหว่างการทาลูปลูปหนึ่ง โดยที่ i เป็ น index ของตัวแรก
ให้เราอยูร
ของ subsequence และ j เป็ น index ของตัวสุ ดท้ายของ subsequence
(ซึ่งตัวสุ ดท้ายนี้ทาให้ subsequence มีค่าเป็ นลบ) และ p เป็ น index
ใด ๆ ระหว่าง i+1 กับ j
3
4
1
i
5/27/2016
-3
-9
p
j
อ. ดร. วิษณุ โคตรจรัส
1
5
31
วิธีการแก้ max sub sum แบบที่ 4 (ต่ อ 2)
ข้อสังเกตที่สอง (ต่อ)
ขั้นต่อไปของลูปก็น่าจะเป็ นการเลื่อน j ออกไป ซึ่ ง
• ถ้า a[j] เป็ นลบ เราก็ไม่ได้ maximum subsequence sum ที่ดีข้ ึน
ค่าของ maximum subsequence sum ก็จะยังคงไม่เปลี่ยน
• ถ้า a[j] เป็ นบวก เราก็จะได้ค่า a[i]+…+a[j] ที่มากขึ้นกว่า
a[i]+…+a[j ตัวเก่า] แต่เพราะ a[i]+…+a[j ตัวเก่า] เป็ นลบ ค่า
ผลรวมจึงไม่มีทางสู ค้ ่าของ maximum subsequence sum ที่เก็บ
สะสมมาได้ หรื อแม้แต่จะสู ค้ ่า a[j ตัวใหม่] เพียวๆก็ไม่ได้
ดังนั้นจึงสรุ ปได้วา่ ถ้ามี subsequence เป็ นลบแล้วละก็ เราไม่
ต้องทาการเลื่อน j ให้เสี ยเวลา เราควรไปเลื่อน i เลย
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
32
วิธีการแก้ max sub sum แบบที่ 4 (ต่ อ 3)
แต่ควรจะเลื่อน i ไปแค่หนึ่ งช่องเท่านั้นหรื อ?
จากสมมติฐาน เรารู ้วา่ a[j] เท่านั้นที่ทาให้ a[i]+…+a[j] มีค่าเป็ น
ลบ เพราะฉะนั้น การเลื่อน i เพิ่มไปหนึ่งตาแหน่งในช่วง i ถึง p ก็มี
แต่ทาให้ค่าผลรวมจาก a[i] ถึง a[p] (โดย p เป็ นค่าที่อยูร่ ะหว่าง i ถึง
j) ลดลงจากค่ามากที่สุดที่เคยมี นัน่ คือ ถ้าเลื่อน j จาก i ในขอบเขตนี้
ยังไงก็ไม่มีทางเพิ่ม max sub sum ได้
เพราะฉะนั้นถ้าจะให้ max sub sum มีค่ามากขึ้นได้อีก มีทางเดียว
คือเราต้องเริ่ มคิดจากตาแหน่งที่ j+1 นัน่ คือเลื่อน i ไปที่ j+1 เลย
3
4
1
i
5/27/2016
-3
-9
p
j
อ. ดร. วิษณุ โคตรจรัส
1
5
33
วิธีการแก้ max sub sum แบบที่ 4 (ต่ อ 4)
1: int maxsubsumOptimum (int[] array) {
2:
int maxSum = 0, theSum = 0;
3:
for (int j = 0; j < a.length; j++) {
4:
theSum = theSum + array [j];
5:
if ( theSum > maxSum) {
6:
maxSum = theSum;
7:
} else if (theSum < 0) {
// ถ้าเจอ a[j] ที่ทาให้ท้ งั
8:
//sequence เป็ นลบ
9:
theSum = 0;
// นี่คือจะมาเริ่ มคิดใหม่จาก
10:
// j+1
11:
}
12:
}
13:
return maxSum;
14: }
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
34
การมี log ใน BIG O
ถ้าเราสามารถใช้เวลาคงที่ (O(1)) ในการแบ่งปั ญหาปัญหาหนึ่ง
ออกเป็ นส่ วน ๆ เท่า ๆ กัน (วิธีที่ 3 ของ maximum subsequence
sum) ปัญหานั้นจะมี Big O เป็ น O(log n)
เรามักสมมติให้มีการอ่านข้อมูลเข้าเรี ยบร้อยแล้ว มิฉะนั้นแค่การ
อ่านข้อมูลเข้าก็เป็ น O(n) แล้ว
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
35
ตัวอย่ างโปรแกรมที่เป็ น O(log n)
หา 5 ในอาร์เรย์ที่มีการจัดเรี ยงตัวเลขจากน้อยไปมากเรี ยบร้อย
แล้ว
ถ้าใช้การไล่หาจากสมาชิกอาร์เรย์ตวั แรก (Big O คือ O(n)) จะ
เสี ยเวลาได้
ก็ดูตรงกลางแล้วแบ่งข้างหาดีกว่า (Binary Search)
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
36
int binarySearch (int[] a, int x) {
int left = 0, right = a.length – 1;
while (left <=right) {
int mid = (left + right)/2;
if (a[mid] < x ) {
left = mid + 1;
} else if (a[mid] > x) {
right = mid – 1;
} else {
return mid;
}
}
return -1; // ถึงตรงนี้แสดงว่าไม่เจอเลย
}5/27/2016
อ. ดร. วิษณุ โคตรจรัส
Big O = O(log2 n)
37
ตัวอย่ าง O(log n) (ต่ อ)
หาตัวหารร่ วมมาก
long gcd (long m , long n) {
while (n!=0) {
long rem = m%n;
m = n;
n = rem;
}
แล้ว Big O จะหายังไง?
return m;
}
การลดลงของเศษจะบอกว่า Big O (การวนลูป) เป็ นเท่าไร ซึ่งค่าเศษ
ลดลงอย่างไม่เป็ นสัดส่ วนเลย
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
38
การหา big O ของโปรแกรมหารร่ วมมาก
ต้องใช้นิยามดังข้างล่าง
ถ้า M > N แล้ว M mod N < M/2 เราพิสูจน์ได้ดงั นี้
ถ้ า N <= M/2: เนื่ องจากเศษต้ องน้ อยกว่ า N เพราะฉะนั้น เศษก็มีค่าน้ อยกว่ า M/2
โดยปริยาย
ถ้ า N > M/2: M หาร N จะได้ 1 กับเศษ M-N นั่นคือ 1 กับเศษ M – (> M/2)
เพราะฉะนั้น เศษจะน้ อยกว่ า M/2 โดยปริยาย
จากนิยามนี้ เศษของลูปที่ n จะถูกนามาใช้เป็ น m เริ่ มต้นของลูปที่ (n+2) เศษ
จากลูปที่ (n+2) จะต้องมีค่าน้อยกว่าครึ่ งหนึ่งของเศษจากลูปที่ n นี่แสดงว่า
เมื่อลูปผ่านไปสองครั้ง ขนาดของ เศษลดลงเกินหรื อเท่ากับครึ่ งหนึ่งแน่ ๆ
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
39
ตัวอย่ าง O(log n) (ต่ อ2)
การยกกาลังเลข xn ด้วยวิธีแบ่งแยกและเอาชนะ
long power (long x, int n) {
if (n==0)
Big O คือ O (log2 n)
return 1;
ปัญหาถูกแบ่ งเป็ น 2 ครึ่ง
if (isEven (n))
(ประมาณ) เท่ ากันในแต่ ละการ
ยกใช้ method
return power (x*x,เรีn/2);
else
return power (x*x, n/2)*x;
}
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
40
นิยามเกีย่ วกับ O(log n)
logk n = O(n) เมื่อ k เป็ นค่าคงที่
(นิ ยามนี้ บอกเราว่า logarithm function มีอต
ั ราการเพิ่มต่ามาก)
ฟังก์ชนั่ f(n) = loga n มีค่า big O เป็ น O(logb n) (a และ b เป็ น
จานวนบวกที่ไม่ใช่ 1)
(สรุ ปคือ log function มี growth rate เท่ากัน)
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
41
พิสูจน์ นิยามทีว่ ่ า log มี growth rate เท่ ากัน
ให้ log
a
n x และ log
b
n y
a x n , b y n
x ln a y ln b ln n
x ln a y ln b
log
a
n * ln a log
b
n * ln b
ln b
log a n log b n *
(log
ln a
log
5/27/2016
a
n O (log
อ. ดร. วิษณุ โคตรจรัส
b
b
n) * c
n)
42
Runtime -น้ อย(บน)ไปมาก(ล่าง)
c
log n
logk n
n
n log n
n2
n3
2n
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
43
นิยามอื่น ๆ นอกเหนือจาก Big O
Big Omega ( )
T(N) = (g(N)) ถ้ามีค่าคงที่ C และ N0 ซึ่ง
T(N) >= C g(N) โดย N>=N0
จากนิ ยาม ถ้า f(N) = (N2) แล้วล่ะก็ f(N) = (N) = (N1/2) แต่
เราควรเลือกอันที่ค่าใกล้ความจริ งที่สุด
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
44
นิยามอื่น ๆ นอกเหนือจาก Big O (ต่ อ)
Big Theta ( )
T(N) = (h(N)) ก็ต่อเมื่อ T(N) = O(h(N)) และ T(N) = (h(N))
(คือมี c1, c2, N0 ที่ c1*h(N) <= T(N) <= c2*h(N) สาหรับ N >= N0
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
45
นิยามอื่น ๆ นอกเหนือจาก Big O (ต่ อ 2)
small O
T(N) = o(p(N)) ถ้า T(N) = O(p(N)) แต่ T(N) (p(N))
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
46
ข้ อสั งเกตจากนิยามทั้งหลาย
T(N) = O(f(N)) มีความหมายเหมือนกับ f(N) = (T(N))
เราสามารถเรี ยกได้วา่ f(N) เป็ น “upper bound” ของ T(N) และ T(N)
ก็ถือได้วา่ เป็ น lower bound ของ f(N)
f(N) = N2 และ g(N) = 2N2 มีค่า Big O และ Big เท่ากัน นัน่ คือ
f(N) = (g(N))
f(N) = N2 มี Big O ได้หลายค่า (เช่น O(N3), O(N4)) แต่ค่าที่ดีที่สุด
คือ O(N2)
เราสามารถใช้สมการ f(N) = (N2) เป็ นการบอกว่า ค่า Big O -คือ
N2 นี้เป็ น Big O ที่ดีที่สุด
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
47
จากข้ อสั งเกต เราได้ นิยามล่าสุ ดดังนี้
ถ้า T(N) คือ Polynomial degree k แล้ว
T(N) = (Nk)
จากนิยามนี้ ถ้า T(N) = 5N4 + 4N3 + N เราจะได้วา่ T(N) =
(N4)
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
48
Best case Worst case และ Average case
worst case คือ เวลาเมื่อการ run ต้องใช้จานวนขั้นตอนมากที่สุด
ส่ วน best case คือ เวลาในการ run ที่นอ้ ยที่สุดที่เป็ นไปได้
average case (เวลาเฉลี่ย) ล่ะ?
ดูวา่ มีกี่ input (ข้อมูลเข้า) เข้าโปรแกรม
สาหรับแต่ละ input ดูวา่ โปรแกรมใช้กี่ข้ น
ั ตอน (unit time) ในการ run
ค่าเฉลี่ย (average case running time) = ผลรวมของจานวน unit time จากทุก
input / จานวน input
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
49
Average case (ต่ อ)
แต่การหาค่าเฉลี่ยอย่างง่ายนี้ ตั้งอยูบ่ นสมมติฐานว่า
input แต่ละแบบมีอต
ั ราการเกิดขึ้นเท่ากัน
ถ้าจะให้ไม่ตอ
้ งมีสมมติฐานนี้
เราต้องเอาค่าความน่ าจะเป็ นในการเกิดของ input แบบต่าง ๆ เข้า
มาคิดด้วยนัน่ คือ
Average case = i ความน่ าจะเป็ นของ inputi * ค่า unit time
เมื่อใช้ inputi
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
50
ตัวอย่ างการหา Average case
ถ้าเราต้องการหา x ในอาร์เรย์ขนาด n
Best case เกิดขึ้นเมื่อเจอ x ในช่องแรก
Worst case เกิดขึ้นเมื่อ x อยูช่ ่องสุ ดท้ายในอาร์เรย์ (หรื ออาจไม่อยู่
เลย)
Average case
สมมติวา่ แต่ละช่องอาร์ เรย์มีโอกาสที่จะมี x เท่ากัน
เพราะฉะนั้น โอกาสที่ x จะอยูใ่ นช่องช่องหนึ่ ง คือ 1/n
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
51
ตัวอย่ างการหา Average case (ต่ อ)
Average Case running time = 1/n * (จานวนขั้นตอนที่ใช้ในการหา
เมื่อ x อยูช่ ่องที่ 1) + 1/n * (จานวนขั้นตอนที่ใช้ในการหาเมื่อ x อยู่
ช่องที่ 2) + ... + 1/n * (จานวนขั้นตอนที่ใช้ในการหาเมื่อ x อยูช่ ่องที่
n หรื ออาจไม่อยูเ่ ลย)
= (1 + 2 +… + n) / n = (n+1)/2
= O(n) = big O ของ worst case
5/27/2016
อ. ดร. วิษณุ โคตรจรัส
52