ทำไมกรณีที่เลวร้ายที่สุดสำหรับฟังก์ชั่นนี้ O (n ^ 2)


44

ฉันพยายามสอนตัวเองถึงวิธีการคำนวณสัญกรณ์ BigO สำหรับฟังก์ชั่นโดยพลการ ฉันพบฟังก์ชันนี้ในตำราเรียน หนังสือยืนยันว่าฟังก์ชันนั้นเป็น O (n 2 ) มันให้คำอธิบายว่าทำไมถึงเป็นเช่นนี้ แต่ฉันพยายามที่จะติดตาม ฉันสงสัยว่าใครบางคนอาจแสดงคณิตศาสตร์ให้ฉันฟังได้ไหมว่าทำไมถึงเป็นเช่นนั้น ฉันเข้าใจว่ามันเป็นอะไรที่น้อยกว่า O (n 3 ) แต่ฉันไม่สามารถลงจอดบน O (n 2 ) ได้อย่างอิสระ

สมมติว่าเราได้รับสามลำดับของตัวเลข A, B และ C เราจะสมมติว่าไม่มีลำดับแต่ละรายการมีค่าซ้ำกัน แต่อาจมีบางตัวเลขที่อยู่ในลำดับที่สองหรือสาม ปัญหาความไม่ลงรอยกันชุดสามทางคือการตรวจสอบว่าจุดตัดของทั้งสามลำดับนั้นว่างเปล่าหรือไม่นั่นคือไม่มีองค์ประกอบ x เช่น x x A, x ∈ B, และ x ∈ C

อนึ่งนี่ไม่ใช่ปัญหาการบ้านสำหรับฉัน - เรือลำนั้นแล่นไปเมื่อหลายปีก่อน) ฉันแค่พยายามฉลาดขึ้น

def disjoint(A, B, C):
        """Return True if there is no element common to all three lists."""  
        for a in A:
            for b in B:
                if a == b: # only check C if we found match from A and B
                   for c in C:
                       if a == c # (and thus a == b == c)
                           return False # we found a common value
        return True # if we reach this, sets are disjoint

[แก้ไข] ตามตำรา:

ในรุ่นที่ปรับปรุงแล้วมันไม่ได้เป็นเพียงแค่เราประหยัดเวลาถ้าเราโชคดี เราอ้างว่าเวลาที่เลวร้ายที่สุดในการทำงานสำหรับ disjoint คือ O (n 2 )

คำอธิบายของหนังสือที่ฉันพยายามทำตามคือ:

เพื่อพิจารณาถึงเวลาการทำงานโดยรวมเราตรวจสอบเวลาที่ใช้ในการประมวลผลโค้ดแต่ละบรรทัด การจัดการสำหรับ for loop over A ต้องใช้เวลา O (n) การจัดการวนรอบสำหรับบัญชี B รวมเป็นเวลา O (n 2 ) เนื่องจากการวนซ้ำนั้นดำเนินการในเวลาที่ต่างกัน การทดสอบ a == b จะถูกประเมิน O (n 2 ) ครั้ง เวลาที่เหลือจะขึ้นอยู่กับจำนวนการจับคู่ (a, b) ดังที่เราได้สังเกตเห็นว่ามีอยู่ไม่เกิน n คู่ดังกล่าวดังนั้นการจัดการของลูปผ่าน C และคำสั่งภายในเนื้อความของลูปนั้นใช้เวลา O (n 2 ) มากที่สุด เวลาทั้งหมดที่ใช้คือ O (n 2 )

(และเพื่อให้เครดิตที่เหมาะสม ... ) หนังสือเล่มนี้คือ: โครงสร้างข้อมูลและอัลกอริทึมใน Python โดย Michael T. Goodrich และ ทั้งหมด Wiley Publishing, pg. 135

[แก้ไข] เหตุผล ด้านล่างนี้เป็นรหัสก่อนการเพิ่มประสิทธิภาพ:

def disjoint1(A, B, C):
    """Return True if there is no element common to all three lists."""
       for a in A:
           for b in B:
               for c in C:
                   if a == b == c:
                        return False # we found a common value
return True # if we reach this, sets are disjoint

ในข้างต้นคุณจะเห็นได้อย่างชัดเจนว่านี่คือ O (n 3 ) เพราะแต่ละวงจะต้องวิ่งให้เต็มที่ หนังสือเล่มนี้จะยืนยันว่าในตัวอย่างง่าย ๆ (รับแรก) วงที่สามเป็นเพียงความซับซ้อนของ O (n 2 ) ดังนั้นสมการความซับซ้อนไปเป็น k + O (n 2 ) + O (n 2 ) ซึ่งในที่สุดผลตอบแทน O (n 2 )

แม้ว่าฉันจะไม่สามารถพิสูจน์ได้ว่าเป็นกรณีนี้ (เช่นคำถาม) ผู้อ่านสามารถยอมรับว่าความซับซ้อนของอัลกอริทึมที่ทำให้เข้าใจง่ายมีค่าน้อยกว่าของเดิม

[แก้ไข] และเพื่อพิสูจน์ว่าเวอร์ชันที่ง่ายคือกำลังสอง:

if __name__ == '__main__':
    for c in [100, 200, 300, 400, 500]:
        l1, l2, l3 = get_random(c), get_random(c), get_random(c)
        start = time.time()
        disjoint1(l1, l2, l3)
        print(time.time() - start)
        start = time.time()
        disjoint2(l1, l2, l3)
        print(time.time() - start)

อัตราผลตอบแทน:

0.02684807777404785
0.00019478797912597656
0.19134306907653809
0.0007600784301757812
0.6405444145202637
0.0018095970153808594
1.4873297214508057
0.003167390823364258
2.953308343887329
0.004908084869384766

เนื่องจากความแตกต่างที่สองมีค่าเท่ากันฟังก์ชันที่เรียบง่ายจึงเป็นกำลังสอง:

ป้อนคำอธิบายรูปภาพที่นี่

[แก้ไข] และยังมีข้อพิสูจน์เพิ่มเติม:

ถ้าฉันถือว่ากรณีที่เลวร้ายที่สุด (A = B! = C)

if __name__ == '__main__':
    for c in [10, 20, 30, 40, 50]:
        l1, l2, l3 = range(0, c), range(0,c), range(5*c, 6*c)
        its1 = disjoint1(l1, l2, l3)
        its2 = disjoint2(l1, l2, l3)
        print(f"iterations1 = {its1}")
        print(f"iterations2 = {its2}")
        disjoint2(l1, l2, l3)

อัตราผลตอบแทน:

iterations1 = 1000
iterations2 = 100
iterations1 = 8000
iterations2 = 400
iterations1 = 27000
iterations2 = 900
iterations1 = 64000
iterations2 = 1600
iterations1 = 125000
iterations2 = 2500

การใช้การทดสอบผลต่างครั้งที่สองผลลัพธ์ของกรณีที่เลวร้ายที่สุดคือสมการกำลังสอง

ป้อนคำอธิบายรูปภาพที่นี่


6
ไม่ว่าหนังสือเล่มนี้จะผิดหรือการถอดความของคุณ
candied_orange

6
Nope ผิดผิดโดยไม่คำนึงว่าอ้างดีแค่ไหน อธิบายว่าทำไมเราไม่สามารถสรุปได้ว่าสิ่งเหล่านี้เป็นไปอย่างที่เลวร้ายที่สุดที่พวกเขาสามารถทำได้เมื่อทำการวิเคราะห์ O ขนาดใหญ่หรือยอมรับผลลัพธ์ที่คุณได้รับ
candied_orange

8
@candied_orange; ฉันได้เพิ่มเหตุผลเพิ่มเติมเพื่อความสามารถที่ดีที่สุดของฉัน - ไม่ใช่ชุดที่แข็งแรงของฉัน ฉันขอให้คุณให้โอกาสที่คุณอาจไม่ถูกต้องอีกครั้ง คุณได้ทำจุดของคุณเอาไปอย่างถูกต้อง
SteveJ

8
ตัวเลขสุ่มไม่ใช่กรณีที่เลวร้ายที่สุดของคุณ นั่นไม่ได้พิสูจน์อะไรเลย
Telastyn

7
อ่า ถูก "ไม่มีลำดับมีค่าซ้ำกัน" จะเปลี่ยนกรณีที่เลวร้ายที่สุดเนื่องจาก C สามารถเรียกหนึ่งครั้งต่อ A. ใด ๆ ขออภัยเกี่ยวกับความยุ่งยาก - นั่นคือสิ่งที่ฉันได้รับใน stackexchange ล่าช้าในวันเสาร์: D
Telastyn

คำตอบ:


63

หนังสือเล่มนี้ถูกต้องแน่นอนและเป็นข้อโต้แย้งที่ดี โปรดทราบว่าการกำหนดเวลาไม่ใช่ตัวบ่งชี้ที่เชื่อถือได้สำหรับความซับซ้อนของอัลกอริทึม การกำหนดเวลาอาจพิจารณาเฉพาะการกระจายข้อมูลแบบพิเศษหรือกรณีทดสอบอาจมีขนาดเล็กเกินไป: ความซับซ้อนของอัลกอริทึมจะอธิบายวิธีการใช้ทรัพยากรหรือรันไทม์ของเครื่องชั่งเกินขนาดอินพุตที่มีขนาดใหญ่พอสมควร

หนังสือทำให้เหตุผลที่ซับซ้อนคือ O (n²) เนื่องจากif a == bมีการป้อนสาขามากที่สุดnครั้ง นี่ไม่ชัดเจนเนื่องจากลูปยังคงเขียนเป็นซ้อนอยู่ มันชัดเจนมากขึ้นถ้าเราแยกมัน:

def disjoint(A, B, C):
  AB = (a
        for a in A
        for b in B
        if a == b)
  ABC = (a
         for a in AB
         for c in C
         if a == c)
  for a in ABC:
    return False
  return True

ตัวแปรนี้ใช้เครื่องกำเนิดไฟฟ้าเพื่อแสดงผลลัพธ์ระดับกลาง

  • ในเครื่องกำเนิดไฟฟ้าABเราจะมีที่มากที่สุด nองค์ประกอบ (เพราะรับประกันว่ารายการการป้อนข้อมูลจะไม่ได้มีรายการซ้ำ) และการผลิตเครื่องกำเนิดไฟฟ้าใช้เวลา O (n²) ความซับซ้อน
  • การผลิตเครื่องกำเนิดไฟฟ้าABCนั้นเกี่ยวข้องกับการวนรอบตัวกำเนิดABความยาวnและCความยาวมากกว่าnดังนั้นความซับซ้อนของอัลกอริทึมก็คือ O (n²) เช่นกัน
  • การดำเนินการเหล่านี้ไม่ซ้อนกัน แต่เกิดขึ้นอย่างอิสระดังนั้นความซับซ้อนทั้งหมดคือ O (n² + n²) = O (n²)

เนื่องจากคู่ของรายการอินพุตสามารถตรวจสอบได้ตามลำดับจึงเป็นไปตามการพิจารณาว่าจำนวนรายการใด ๆ ที่แยกกันสามารถทำได้ในเวลา O (n²)

การวิเคราะห์นี้ไม่แน่ชัดเพราะถือว่าทุกรายการมีความยาวเท่ากัน เราสามารถพูดได้อย่างแม่นยำมากขึ้นซึ่งABมีความยาวขั้นต่ำสุด (| A |, | B |) และการผลิตมีความซับซ้อน O (| A | • | B |) การผลิตABCมีความซับซ้อน O (ขั้นต่ำ (| A |, | B |) • | C |) ความซับซ้อนทั้งหมดนั้นขึ้นอยู่กับวิธีการสั่งซื้อรายการอินพุต ด้วย | A | ≤ | B | ≤ | C | เราได้รับความซับซ้อนกรณีที่เลวร้ายที่สุดของ O (| A | • | C |)

โปรดทราบว่าการชนะอย่างมีประสิทธิภาพนั้นเป็นไปได้หากคอนเทนเนอร์อินพุตอนุญาตให้ทำการทดสอบการเป็นสมาชิกอย่างรวดเร็วแทนที่จะต้องวนซ้ำองค์ประกอบทั้งหมด นี่อาจเป็นกรณีที่มีการเรียงลำดับเพื่อให้สามารถทำการค้นหาแบบไบนารีหรือเมื่อพวกเขาถูกตั้งค่าแฮช หากไม่มีลูปซ้อนกันอย่างชัดเจนจะมีลักษณะดังนี้:

for a in A:
  if a in B:  # might implicitly loop
    if a in C:  # might implicitly loop
      return False
return True

หรือในเวอร์ชันที่อิงกับตัวสร้าง:

AB = (a for a in A if a in B)
ABC = (a for a in AB if a in C)
for a in ABC:
  return False
return True

4
นี่จะชัดเจนกว่านี้ถ้าเรายกเลิกnตัวแปรเวทนี้และพูดคุยเกี่ยวกับตัวแปรจริงที่เล่น
Alexander

15
@code_dredd ไม่มันไม่ได้มีการเชื่อมต่อโดยตรงกับรหัส มันเป็นนามธรรมที่วาดภาพlen(a) == len(b) == len(c)ซึ่งแม้ว่าจะเป็นจริงในบริบทของการวิเคราะห์ความซับซ้อนของเวลา แต่มีแนวโน้มที่จะสร้างความสับสนในการสนทนา
Alexander

10
อาจจะบอกว่ารหัสของ OP มีความซับซ้อนของตัวพิมพ์เล็กที่สุด O (| A | • | B | + min (| A |, | B |) • | C |) เพียงพอที่จะกระตุ้นให้เกิดความเข้าใจ?
Pablo H

3
อีกสิ่งหนึ่งเกี่ยวกับการทดสอบเวลา: ตามที่คุณทราบพวกเขาไม่ได้ช่วยคุณในการทำความเข้าใจสิ่งที่เกิดขึ้น ในทางกลับกันพวกเขาดูเหมือนจะให้ความมั่นใจเพิ่มเติมกับคุณในการยืนถึงข้อผิดพลาดต่าง ๆ แต่อ้างอย่างแข็งขันว่าหนังสือเล่มนี้ผิดอย่างเห็นได้ชัดดังนั้นมันจึงเป็นสิ่งที่ดีและในกรณีนี้การทดสอบของคุณเอาชนะการโบกมืออย่างง่าย เพื่อความเข้าใจวิธีทดสอบที่มีประสิทธิภาพมากขึ้นคือการรันในดีบักเกอร์ที่มีจุดพัก (หรือเพิ่มการพิมพ์ค่าของตัวแปร) ที่รายการของแต่ละลูป
sdenham

4
"โปรดทราบว่าการกำหนดเวลาไม่ใช่ตัวบ่งชี้ที่มีประโยชน์ของความซับซ้อนของอัลกอริทึม" ฉันคิดว่านี่จะแม่นยำกว่านี้หากกล่าวว่า "เข้มงวด" หรือ "เชื่อถือได้" แทนที่จะเป็น "มีประโยชน์"
สะสม

7

โปรดทราบว่าหากองค์ประกอบทั้งหมดแตกต่างกันในแต่ละรายการซึ่งถือว่าคุณสามารถทำซ้ำ C เพียงครั้งเดียวสำหรับแต่ละองค์ประกอบใน A (ถ้ามีองค์ประกอบใน B ซึ่งเท่ากัน) ดังนั้นวงในคือจำนวนทั้งหมด O (n ^ 2)


3

เราจะสมมติว่าไม่มีลำดับของแต่ละบุคคลที่ซ้ำกัน

เป็นข้อมูลที่สำคัญมาก

มิฉะนั้นกรณีที่แย่ที่สุดของรุ่นที่ปรับปรุงแล้วจะยังคงเป็น O (n³) เมื่อ A และ B เท่ากันและมีองค์ประกอบหนึ่งซ้ำ n ครั้ง:

i = 0
def disjoint(A, B, C):
    global i
    for a in A:
        for b in B:
            if a == b:
                for c in C:
                    i+=1
                    print(i)
                    if a == c:
                        return False 
    return True 

print(disjoint([1] * 10, [1] * 10, [2] * 10))

ผลลัพธ์ใด:

...
...
...
993
994
995
996
997
998
999
1000
True

ผู้เขียนคิดว่า O (n³) กรณีที่เลวร้ายที่สุดไม่ควรเกิดขึ้น (ทำไม?) และ "พิสูจน์" ว่ากรณีที่เลวร้ายที่สุดคือ O (n²)

การปรับให้เหมาะสมที่แท้จริงคือการใช้ชุดหรือ dicts เพื่อทดสอบการรวมใน O (1) ในกรณีนั้นdisjointจะเป็น O (n) สำหรับทุกอินพุต


ความคิดเห็นล่าสุดของคุณน่าสนใจมากไม่ได้คิดอย่างนั้น คุณกำลังแนะนำว่าเกิดจากความสามารถในการดำเนินการสาม O (n) ในซีรีส์หรือไม่?
SteveJ

2
หากคุณไม่ได้รับแฮชที่สมบูรณ์แบบด้วยอย่างน้อยหนึ่ง bucket ต่อองค์ประกอบอินพุตคุณจะไม่สามารถทดสอบการรวมใน O (1) ชุดที่เรียงลำดับมักจะมีการค้นหา O (log n) เว้นแต่ว่าคุณกำลังพูดถึงค่าใช้จ่ายเฉลี่ย แต่นั่นไม่ใช่สิ่งที่เป็นคำถาม ถึงกระนั้นการมีชุดเลขฐานสองที่สมดุลได้รับยาก O (n log n) เป็นเรื่องเล็กน้อย
Jan Dorniak

@JanDorniak: ความคิดเห็นที่ยอดเยี่ยมขอบคุณ ตอนนี้มันค่อนข้างอึดอัดใจ: ฉันไม่สนใจกรณีที่แย่ที่สุดkey in dictเช่นเดียวกับที่ผู้เขียนทำ : - / ในการป้องกันของฉันฉันคิดว่ามันยากที่จะหา dict ด้วยnปุ่มและnการชนกันของแฮชมากกว่าแค่สร้างรายการที่มีnค่าซ้ำกัน และด้วย set หรือ dict ก็ไม่สามารถมีค่าซ้ำกันได้ ดังนั้นกรณีที่เลวร้ายที่สุดที่เลวร้ายที่สุดคือ O (n²) ฉันจะอัปเดตคำตอบของฉัน
Eric Duminil

2
@JanDorniak ฉันคิดว่าชุดและ dicts เป็นตารางแฮชใน python ซึ่งตรงข้ามกับต้นไม้สีแดงดำใน C ++ ดังนั้นกรณีที่เลวร้ายที่สุดที่แน่นอนคือแย่กว่ามากถึง 0 (n) สำหรับการค้นหา แต่กรณีโดยเฉลี่ยคือ O (1) เมื่อเทียบกับ O (log n) สำหรับ C ++ wiki.python.org/moin/TimeComplexity ระบุว่าเป็นคำถามงูหลามและโดเมนของปัญหานำไปสู่แนวโน้มที่สูงของประสิทธิภาพของเคสโดยเฉลี่ยฉันไม่คิดว่าการอ้างสิทธิ์ O (1) นั้นแย่
Baldrickk

3
ฉันคิดว่าฉันเห็นปัญหาที่นี่: เมื่อผู้เขียนพูดว่า "เราจะสมมติว่าไม่มีลำดับแต่ละรายการมีค่าซ้ำกัน" นั่นไม่ใช่ขั้นตอนในการตอบคำถาม มันเป็นเงื่อนไขก่อนที่คำถามจะได้รับการแก้ไข เพื่อจุดประสงค์ในการสอนสิ่งนี้กลายเป็นปัญหาที่ไม่น่าสนใจไปสู่ปัญหาที่ท้าทายความเชื่อมั่นของประชาชนเกี่ยวกับบิ๊กโอและดูเหมือนว่าจะประสบความสำเร็จในการตัดสินโดยจำนวนคนที่ยืนยันอย่างหนักว่า O (n²) .. นอกจากนี้ในขณะที่ moot อยู่ที่นี่การนับจำนวนขั้นตอนในตัวอย่างหนึ่งไม่ใช่คำอธิบาย
sdenham

3

ในการใส่คำต่างๆลงในข้อกำหนดที่หนังสือของคุณใช้:

ฉันคิดว่าคุณไม่มีปัญหาในการทำความเข้าใจว่าการตรวจสอบa == bเป็นกรณีที่เลวร้ายที่สุด O (n 2 )

ตอนนี้ในกรณีที่เลวร้ายที่สุดสำหรับวงที่สามทุกaในAมีการแข่งขันBเพื่อให้วงที่สามจะถูกเรียกว่าทุกครั้ง ในกรณีที่aไม่มีอยู่Cมันจะทำงานทั้งCชุด

กล่าวอีกนัยหนึ่งคือ 1 ครั้งสำหรับทุก ๆa1 ครั้งสำหรับทุก ๆcหรือ n * n O (n 2 )

ดังนั้นจึงมี O (n 2 ) + O (n 2 ) ที่หนังสือของคุณชี้


0

เคล็ดลับของวิธีการที่เหมาะสมที่สุดคือการตัดมุม เฉพาะในกรณีที่ a และ b ตรงกัน c จะได้รับมูลค่าดู ตอนนี้คุณอาจคิดว่าในกรณีที่เลวร้ายที่สุดคุณจะต้องประเมินแต่ละค นี่ไม่เป็นความจริง.

คุณอาจคิดว่ากรณีที่แย่ที่สุดคือการตรวจสอบ a == b ทุกครั้งจะส่งผลให้เกิดการเรียกใช้มากกว่า C เนื่องจากการตรวจสอบทุกครั้งสำหรับ a == b จะส่งคืนการจับคู่ แต่สิ่งนี้เป็นไปไม่ได้เพราะเงื่อนไขสำหรับสิ่งนี้ขัดแย้งกัน เพื่อให้สามารถใช้งานได้คุณจะต้องมี A และ A ที่มีค่าเดียวกัน พวกเขาอาจถูกสั่งแตกต่างกัน แต่แต่ละค่าใน A จะต้องมีค่าที่ตรงกันใน B

ตอนนี้ที่นี่เป็นนักเตะ ไม่มีวิธีในการจัดระเบียบค่าเหล่านี้ดังนั้นสำหรับแต่ละ a คุณจะต้องประเมินค่า b ทั้งหมดก่อนที่คุณจะพบคู่ที่ตรงกัน

A: 1 2 3 4 5
B: 1 2 3 4 5

สิ่งนี้จะเกิดขึ้นทันทีเนื่องจากการจับคู่ 1 เป็นองค์ประกอบแรกในทั้งสองซีรี่ส์ เกี่ยวกับอะไร

A: 1 2 3 4 5
B: 5 4 3 2 1

นั่นจะใช้ได้สำหรับการวิ่งครั้งแรกเหนือ A: เฉพาะองค์ประกอบสุดท้ายใน B เท่านั้นที่จะได้รับผลกระทบ แต่การทำซ้ำครั้งถัดไปของ A จะต้องเร็วกว่าเพราะจุดสุดท้ายใน B นั้นถูกครอบครองโดย 1 และแน่นอนว่าจะใช้เวลาเพียงสี่รอบเท่านั้นในครั้งนี้ และสิ่งนี้จะดีขึ้นเล็กน้อยเมื่อทำซ้ำครั้งถัดไป

ตอนนี้ฉันไม่ใช่นักคณิตศาสตร์ดังนั้นฉันจึงไม่สามารถพิสูจน์ได้ว่าจะจบลงที่ O (n2) แต่ฉันรู้สึกได้ถึงอุดตัน


1
ลำดับขององค์ประกอบไม่ได้มีบทบาทที่นี่ ข้อกำหนดที่สำคัญคือไม่มีการซ้ำซ้อน; เหตุผลก็คือว่าลูปสามารถเปลี่ยนเป็นสองO(n^2)วงแยก; ซึ่งให้โดยรวมO(n^2)(ค่าคงที่จะถูกละเว้น)
AnoE

@AnoE แน่นอนลำดับขององค์ประกอบไม่สำคัญ ซึ่งเป็นสิ่งที่ฉันกำลังแสดงให้เห็น
Martin Maat

ฉันเห็นสิ่งที่คุณกำลังพยายามทำและสิ่งที่คุณเขียนไม่ผิด แต่จากมุมมองของ OP คำตอบของคุณส่วนใหญ่แสดงให้เห็นว่าทำไมขบวนความคิดเฉพาะเรื่องจึงไม่เกี่ยวข้อง มันไม่ได้อธิบายถึงวิธีการแก้ปัญหาที่เกิดขึ้นจริง OP ดูเหมือนจะไม่ได้ให้ข้อบ่งชี้ว่าจริง ๆ แล้วเขาคิดว่าสิ่งนี้เกี่ยวข้องกับการสั่งซื้อ ดังนั้นฉันไม่ชัดเจนว่าคำตอบนี้จะช่วย OP อย่างไร
AnoE

-1

ตอนแรกรู้สึกงงงัน แต่คำตอบของ Amon มีประโยชน์จริงๆ ฉันต้องการดูว่าฉันสามารถทำรุ่นที่รัดกุมจริง ๆ :

สำหรับค่าที่กำหนดaในAฟังก์ชั่นเปรียบเทียบaกับที่เป็นไปได้bในBและมันไม่ได้เพียงครั้งเดียว ดังนั้นสำหรับที่กำหนดaจะดำเนินการa == bตรงnเวลา

Bไม่มีรายการที่ซ้ำกัน (ไม่มีรายการที่ทำ) ดังนั้นสำหรับการแข่งขันaจะมีได้ไม่เกินหนึ่งรายการ (นั่นคือกุญแจสำคัญ) ในกรณีที่มีการแข่งขันaจะถูกเปรียบเทียบกับทุก ๆ ที่เป็นไปได้cซึ่งหมายความว่าa == cจะดำเนินการ n ครั้ง ที่ไหนไม่มีการแข่งขันa == cไม่เกิดขึ้นเลย

ดังนั้นสำหรับที่ระบุaมีทั้งnการเปรียบเทียบหรือ2nการเปรียบเทียบ สิ่งนี้เกิดขึ้นได้ทุกaๆ กรณีที่ดีที่สุดคือ (n²) และที่แย่ที่สุดคือ (2n²)

TLDR: ค่าของทุกaเมื่อเทียบกับมูลค่าของทุกbและต่อต้านคุณค่าของทุกcแต่ไม่ได้กับทุกคนรวมกันของและb cปัญหาทั้งสองรวมเข้าด้วยกัน แต่ไม่เพิ่มทวีคูณ


-3

ลองคิดดูด้วยวิธีนี้ตัวเลขบางตัวอาจอยู่ในลำดับที่สองหรือสาม แต่กรณีเฉลี่ยของสิ่งนี้คือสำหรับแต่ละองค์ประกอบในเซต A การค้นหาแบบละเอียดจะดำเนินการใน b มีการรับประกันว่าทุกองค์ประกอบในเซต A จะวนซ้ำ แต่ส่อให้เห็นว่าองค์ประกอบน้อยกว่าครึ่งในเซต b จะถูกวนซ้ำ

เมื่อองค์ประกอบในชุด b ถูกวนซ้ำการวนซ้ำจะเกิดขึ้นหากมีการแข่งขัน นี่หมายความว่ากรณีโดยเฉลี่ยสำหรับฟังก์ชั่นที่แยกจากกันนี้คือ O (n2) แต่กรณีที่แย่ที่สุดแน่นอนสำหรับมันคือ O (n3) ถ้าหนังสือไม่ได้ลงรายละเอียดมันอาจจะให้คำตอบโดยเฉลี่ยสำหรับคุณ


4
หนังสือเล่มนี้ค่อนข้างชัดเจนว่า O (n2) เป็นกรณีที่เลวร้ายที่สุดไม่ใช่กรณีทั่วไป
SteveJ

คำอธิบายของฟังก์ชั่นในรูปของสัญกรณ์ O ใหญ่มักจะให้ขอบเขตบนของอัตราการเติบโตของฟังก์ชั่นเท่านั้น เกี่ยวข้องกับสัญกรณ์ O ใหญ่เป็นสัญกรณ์ที่เกี่ยวข้องหลายอย่างโดยใช้สัญลักษณ์ o, Ω, ωและ kinds เพื่ออธิบายขอบเขตชนิดอื่น ๆ เกี่ยวกับอัตราการเจริญเติบโตของซีซีทีโอติก Wikipedia - Big O
candied_orange

5
"ถ้าหนังสือไม่ได้ลงรายละเอียดมันอาจจะให้คำตอบโดยเฉลี่ยสำหรับคุณ" - อืมมม โดยไม่ต้องมีคุณสมบัติที่ชัดเจนเรามักจะพูดถึงความซับซ้อนขั้นตอนที่เลวร้ายที่สุดในรูปแบบ RAM เมื่อพูดถึงการดำเนินงานเกี่ยวกับโครงสร้างข้อมูลและก็เป็นที่ชัดเจนจากบริบทแล้วเราอาจจะพูดคุยเกี่ยวกับการตัดจำหน่ายซับซ้อนขั้นตอนที่เลวร้ายที่สุดกรณีในรูปแบบแรม หากไม่มีคุณสมบัติที่ชัดเจนเราจะไม่พูดถึงกรณีที่ดีที่สุดกรณีโดยเฉลี่ยกรณีที่คาดหวังความซับซ้อนของเวลาหรือรุ่นอื่น ๆ ยกเว้น RAM
Jörg W Mittag
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.