arrow_backกลับไปที่บันทึกภาคสนาม
COMPUTER SCIENCE เผยแพร่แล้ว 8 Aug 2026

Algorithms That Finish In Time: A Complexity Gut Check

เรียนรู้วิธีการจับตัวอักษรที่ช้าลง ก่อนที่จะส่งออกไป พร้อมตัวอย่าง Big O ที่แท้จริง เกณฑ์มาตรฐาน และการแก้ไขอย่างรวดเร็วสำหรับปัญหาทั่วไป

คุณเขียนฟังก์ชัน รันบนข้อมูลทดสอบของคุณ และมันทำงานได้ดี แล้วมันเข้าไปยังข้อมูลการผลิต — 500,000 แถว แทนที่จะเป็น 500 — และคำขอหมดเวลา สิ่งนี้เกิดขึ้นอย่างต่อเนื่อง และเกือบทั้งหมดเป็นปัญหาความซับซ้อนที่ซ่อนตัวอยู่เบื้องหลังรหัสที่ดูสมเหตุสมผลในขนาดเล็ก

ทำไมแล็ปท็อปของคุณถึงโกหกคุณ

อัลกอริทึม O(n²) ที่ทำงานบนรายการ 100 รายการทำให้เกิด 10,000 การดำเนินการ ในเครื่องใด ๆ นั่นเป็นไปได้ทันที รันอัลกอริทึมเดียวกันบนรายการ 100,000 รายการ และคุณจะอยู่ที่ 10 พันล้านการดำเนินการ — นาทีหรือชั่วโมงแทนที่จะเป็นมิลลิวินาที การกระโดดจาก n ไป n² ไม่รู้สึกอันตรายจนกว่า n จะใหญ่ขึ้น ซึ่งเป็นเหตุผลว่าทำไมมันถึงลื่นผ่านการตรวจสอบรหัสและการทดสอบในท้องถิ่น

ตัวอย่างคลาสสิก: การตรวจหาซ้ำด้วยลูปแบบซ้อน

def has_duplicates(items):
    for i in range(len(items)):
        for j in range(i + 1, len(items)):
            if items[i] == items[j]:
                return True
    return False

นี่คือ O(n²) สลับมันเป็นชุด:

def has_duplicates(items):
    seen = set()
    for item in items:
        if item in seen:
            return True
        seen.add(item)
    return False

ตอนนี้มันคือ O(n) การค้นหาชุดเป็นค่าเฉลี่ย O(1) ดังนั้นฟังก์ชันทั้งหมดจึงปรับขนาดเชิงเส้นแทนที่จะเป็นกำลังสอง บน 10,000 รายการ นั่นคือความแตกต่างระหว่าง 100 ล้านการเปรียบเทียบและ 10,000

วัดก่อนที่คุณจะเพิ่มประสิทธิภาพ

อย่าเดา ใช้ timeit สำหรับการเปรียบเทียบขนาดเล็ก:

import timeit
timeit.timeit(lambda: has_duplicates(list(range(5000))), number=10)

สำหรับฟังก์ชันที่ใหญ่ขึ้น โปรไฟล์กับ cProfile:

python -m cProfile -s cumulative myscript.py

ดูที่คอลัมน์ cumtime ถ้าฟังก์ชันหนึ่งกินเวลารันไทม์ 90% นั่นคือเป้าหมายของคุณ การเพิ่มประสิทธิภาพรหัสที่ไม่ใช่จุดคอขวดจะเสียเวลาของคุณและเพิ่มความซับซ้อนโดยไม่ได้รับ

รูปแบบทั่วไปที่ค่อยๆ ช้าลง

การตรวจสอบการเป็นสมาชิกของรายการซ้ำแล้วซ้ำอีก if x in my_list คือ O(n) สำหรับรายการแต่ O(1) เฉลี่ยสำหรับชุดหรือ dict ถ้าคุณกำลังตรวจสอบการเป็นสมาชิกภายในลูป การตรวจสอบ O(n) นั้นในลูป O(n) ให้ O(n²) โดยรวม สลับรายการสำหรับชุดและคุณจะกลับไป O(n)

การต่อสตริงในลูป ใน Python result += chunk ในลูปบนสตริงคือ O(n²) ในกรณีที่เลวร้ายที่สุด เนื่องจากสตริงไม่เปลี่ยนรูป และการต่อสตริงแต่ละครั้งก็คัดลอกทั้งหมด ใช้ ''.join(chunks) แทน — มันสร้างสตริงเพียงครั้งเดียว

การเรียงลำดับเมื่อคุณไม่จำเป็นต้อง sorted() คือ O(n log n) ถ้าคุณเรียกมันในลูปเพื่อค้นหา max หรือ min เท่านั้นในแต่ละการทำซ้ำ ใช้ max()/min() (O(n)) หรือดีกว่านั้น ฮีป (heapq) ถ้าคุณต้องการส่วนปลายวิ่งซ้ำแล้วซ้ำอีก heapq.nlargest(k, data) คือ O(n log k) ราคาถูกกว่ามากเมื่อเปรียบเทียบกับการเรียงลำดับรายการทั้งหมดเมื่อ k มีขนาดเล็ก

ฟังก์ชันเรียกซ้ำโดยไม่มีการจดจำ Fibonacci แบบไร้เดียวพลันคือ O(2ⁿ) เพราะมันคำนวณปัญหาย่อยเดียวกันซ้ำแล้วซ้ำอีก เพิ่ม functools.lru_cache และมันลดลงเป็น O(n):

from functools import lru_cache

@lru_cache(maxsize=None)
def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

อ่าน Big O จากรหัสจริง อย่างรวดเร็ว

นับลูปแบบซ้อนของอินพุตเดียวกัน — นั่นมักจะเป็นเลขชี้กำลังของคุณ ลูปเดียวคือ O(n) ลูปในลูปคือ O(n²) เว้นแต่ช่วงของลูปด้านในจะหดตัว (เช่นในรูปแบบเหมาะสมที่สุดของฟองจัดเรียง ยังคงเป็น O(n²) กรณีที่เลวร้ายที่สุด แต่มีการเปรียบเทียบน้อยลง) การเรียกซ้ำที่แยกปัญหาออกเป็นครึ่งหนึ่ง เช่น การค้นหาแบบไบนารีหรือการรวมการเรียงลำดับ ชี้ไป O(log n) หรือ O(n log n) การเรียกซ้ำที่แยกออกเป็นหลายการเรียกต่อระดับ เช่น Fibonacci ที่ไร้เดียวพลัน ชี้ไปเวลาเลขชี้กำลัง — สัญญาณที่แข็งแกร่งว่าคุณต้องการการจดจำหรือการเขียนใหม่แบบวนซ้ำ

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

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการวิเคราะห์ความซับซ้อน อัลกอริทึมการเรียงลำดับ และเครื่องมือโปรไฟล์ ให้ตรวจสอบส่วน Python และ Computer Science บน Korra Studio

เขียนด้วยความช่วยเหลือของ AI ตรวจสอบและเผยแพร่โดย Michal Pilch (CISSP), Korra Studio

พร้อมที่จะไปต่อหรือไม่

นี่คือบันทึกหนึ่งจากฐานความรู้ของ Korra Studio — แพลตฟอร์มจับคู่หัวข้อแต่ละหัวข้อกับการฝึกสอนแบบ 1-to-1

เริ่มใช้งานฟรีarrow_forward