ผลต่างระหว่างรุ่นของ "418531 ภาคต้น 2552/โจทยปัญหาอัลกอริทึมแบบแบ่งแยกแล้วเอาชนะ/เฉลยข้อ 1"

จาก Theory Wiki
ไปยังการนำทาง ไปยังการค้นหา
แถว 12: แถว 12:
 
เมื่อนำแนวคิดดังกล่าวมาเขียนเป็น pseudocode จะได้ดังนี้
 
เมื่อนำแนวคิดดังกล่าวมาเขียนเป็น pseudocode จะได้ดังนี้
  
FindN(a,i,j)
+
ให้ j=1
:if j<i
+
FindN(a,j)
 +
:if j<0
 
:: return -1
 
:: return -1
 
:else
 
:else
:: for i=1 to j
+
:: k = 2^j
::: k=2^i
+
:: if a[k]=0 and a[k+1]=1
::: if a[k]=0 and a[k+1]=1
+
::: return k
:::: return k
+
:: else if a[k]=1 and a[k+1]=1
::: else if a[k]=1 and a[k+1]=1
+
::: return FindInSmallInterval(a,2^(j-1),2^j)
:::: return FindN(a,i,k-1)
+
:: else if a[k]= 0 and a[k+1]=0
::: else if a[k]= 0 and a[k+1]=0
+
::: return FindN(a,j+1)
:::: return FindN(a,k+1,j)
 
  
เวลาการทำงานของอัลกอริทึมคือ จะทำทั้งหมด <math> 2^j \, </math> รอบ โดยที่เรารู้ว่า <math> n \leq 2^j < 2n \, </math> ดังนั้นเวลาการทำงานคือ <math> O(2^j)=O(\log n) \,</math> นั่นเอง
+
FindInSmallInterval(a,i,j)
 +
: if j<i
 +
::return -1
 +
: else
 +
:: k = (i+j)/2
 +
:: if a[k]=0 and a[k+1]=1
 +
::: return k
 +
:: else if a[k]=1 and a[k+1]=1
 +
::: return FindInSmallInterval(a,k+1,j)
 +
:: else if a[k]= 0 and a[k+1]=0
 +
::: return FindInSmallInterval(a,i,k-1)
 +
 
 +
เวลาการทำงานของอัลกอริทึมจะแบ่งออกเป็นการค้นหาใน FindN และการค้นหาใน FindInSmallInterval ซึ่ง FindN จะหยุดทำเมื่อค่า <math> n \leq 2^j < 2n \,</math> ซึ่งจะทำงานทั้งหมด <math> j \, </math> รอบ ส่วน FindInSmallInterval จะทำการหาค่า <math> n\, </math> ในช่วงย่อยที่อยู่ระหว่างค่าศูนย์กับหนึ่งแล้ว ซึ่งทำงานทั้งหมด <math> O(\log 2^j)=O(\log n) \,</math> รอบ ดังนั้นเวลาการทำงานทั้งหมดจะเป็น <math> j+O(\log n)=O(\log n) </math> รอบ

รุ่นแก้ไขเมื่อ 08:13, 2 กันยายน 2552

อินพุต: อะเรย์ ที่มีขนาดเป็น infinity ที่มีคุณสมบัติคือสมาชิกชิก ตัวแรกมีค่าเป็นศูนย์ นอกนั้นมีค่าเป็นหนึ่ง

เอาพุต: ค่า

วัตถุ ที่เราต้องทำการตรวจสอบในข้อนี้คือ ตัวเลข 1,2,3,... (หรือ index ของอะเรย์นั่นเอง) ซึ่ง ค่า จะเป็นค่าที่อยู่ในช่วงดังกล่าว และมีเงื่อนไขคือ A[0]ถึง A[n]มีค่าเป็นศูนย์ และ A[n+1] เป็นต้นไปมีค่าเป็นหนึ่ง (เขียนสั้น ๆ คือ A[n]=0 และ A[n+1]=1) แต่โจทย์ต้องการให้เวลาในการหาค่า ดังกล่าวเป็น จากการตัวอย่างการค้นหาในห้องเรียน เราได้เรียน binary search ไปแล้ว เราจะใช้วิธีดังกล่าว

วิธีการค้นหาจะทำดังนี้ ให้เริ่มค้นหาก่อนว่าค่าของอะเรย์ในตำแหน่งต่อไปนี้เป็นศูนย์หรือไม่ ตำแหน่งดังกล่าวคือ จากในห้องเรียนเราได้เห็นแล้วว่าเงื่อนไขของ binary search มีสามเงื่อนไขคือ หยุด ไปทางซ้าย และไปทางขวา สำหรับข้อนี้เงื่อนไขเหล่านี้จะเป็นดังนี้

เงื่อนไขหยุด คือ A[k]=0 and A[k+1]=1
เงื่อนไขไปทางซ้ายคือ A[k]=1 and A[k+1]=1 // แสดงว่าวิ่งเกินมาทางขวาเกินไปแล้ว คำตอบต้องอยู่ทางซ้ายแน่นอน
เงื่อนไขไปทางขวาคือ A[k]=0 and A[k+1]=0 // แสดงว่าวิ่งยังไม่ถึงคำตอบ วิ่งช้าไป คำตอบต้องอยู่ทางขวาแน่นอน

เมื่อนำแนวคิดดังกล่าวมาเขียนเป็น pseudocode จะได้ดังนี้

ให้ j=1 FindN(a,j)

if j<0
return -1
else
k = 2^j
if a[k]=0 and a[k+1]=1
return k
else if a[k]=1 and a[k+1]=1
return FindInSmallInterval(a,2^(j-1),2^j)
else if a[k]= 0 and a[k+1]=0
return FindN(a,j+1)

FindInSmallInterval(a,i,j)

if j<i
return -1
else
k = (i+j)/2
if a[k]=0 and a[k+1]=1
return k
else if a[k]=1 and a[k+1]=1
return FindInSmallInterval(a,k+1,j)
else if a[k]= 0 and a[k+1]=0
return FindInSmallInterval(a,i,k-1)

เวลาการทำงานของอัลกอริทึมจะแบ่งออกเป็นการค้นหาใน FindN และการค้นหาใน FindInSmallInterval ซึ่ง FindN จะหยุดทำเมื่อค่า ซึ่งจะทำงานทั้งหมด รอบ ส่วน FindInSmallInterval จะทำการหาค่า ในช่วงย่อยที่อยู่ระหว่างค่าศูนย์กับหนึ่งแล้ว ซึ่งทำงานทั้งหมด รอบ ดังนั้นเวลาการทำงานทั้งหมดจะเป็น รอบ