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