Divide and Conquer

  • ๋ถ„ํ•  (Divide)

    • ํ•ด๊ฒฐํ•  ๋ฌธ์ œ๋ฅผ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ž‘์€ ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋ˆˆ๋‹ค.

  • ์ •๋ณต (Conquer)

    • ๋‚˜๋ˆˆ ์ž‘์€ ๋ฌธ์ œ๋ฅผ ๊ฐ๊ฐ ํ•ด๊ฒฐํ•œ๋‹ค

  • ํ†ตํ•ฉ (Combine)

    • (ํ•„์š”ํ•˜๋‹ค๋ฉด) ํ•ด๊ฒฐ๋œ ๋‹ต์„ ๋ชจ์€๋‹ค

Top-down Approach (ํ•˜ํ–ฅ์‹ ์ ‘๊ทผ๋ฒ•)

: ๋ถ„ํ•  ์ •๋ณต์€ ํ•˜ํ–ฅ์‹ ์ ‘๊ทผ๋ฒ•์ด๋‹ค

๊ฑฐ๋“ญ์ œ๊ณฑ

  • ๋ฐ˜๋ณต (Iterative) ์•Œ๊ณ ๋ฆฌ์ฆ˜: O(n)

    • C์˜ ๊ฑฐ๋“ญ์ œ๊ณฑ = 1์— ๊ฑฐ๋“ญ์ œ๊ณฑํ•  ๊ฐ’๋งŒํผ C๋ฅผ ๊ณฑํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์—ฐ์‚ฐ ์ˆ˜ํ–‰

  • ๋ถ„ํ•  ์ •๋ณต ๊ธฐ๋ฐ˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜: `O(logn)

    • ๊ฑฐ๋“ญ์ œ๊ณฑ์„ ๋ฐ˜ ์”ฉ ๋‚˜๋ˆ„์–ด์„œ ๊ณฑํ•ด ๋‚˜๊ฐ€๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ํ’€์ด

    • ์ง€์ˆ˜๊ฐ€ 1์ด ๋˜๋ฉด ๋ฐ‘ ์ˆ˜๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜

      • ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ O(log n) ์œผ๋กœ ์ค„์ผ ์ˆ˜ ์žˆ์Œ!

๋ณ‘ํ•ฉ ์ •๋ ฌ (Merge Sort)

  • ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ •๋ ฌ๋œ ์ž๋ฃŒ์˜ ์ง‘ํ•ฉ์„ ๋ณ‘ํ•ฉํ•˜์—ฌ ํ•œ ๊ฐœ์˜ ์ •๋ ฌ๋œ ์ง‘ํ•ฉ์œผ๋กœ ๋งŒ๋“œ๋Š” ๋ฐฉ์‹

  • ๋ถ„ํ•  ์ •๋ณต ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํ™œ์šฉ

    • ์ž๋ฃŒ๋ฅผ ์ตœ์†Œ ๋‹จ์œ„์˜ ๋ฌธ์ œ๊นŒ์ง€ ๋‚˜๋ˆˆ ํ›„์— ์ฐจ๋ก€๋กœ ์ •๋ ฌํ•˜์—ฌ ์ตœ์ข… ๊ฒฐ๊ณผ๋ฅผ ์–ป์–ด๋ƒ„

    • top-down ๋ฐฉ์‹

  • ์‹œ๊ฐ„ ๋ณต์žก๋„

    • O(nlogn)

ex)

def merge(left, right):
    result = [] # ๋‘ ๊ฐœ์˜ ๋ถ„ํ• ๋œ list๋ฅผ ๋ณ‘ํ•ฉํ•˜์—ฌ result๋ฅผ ๋งŒ๋“ฆ

    while len(left) > 0 and len(right) > 0: # ์–‘์ชฝ list์— ์›์†Œ๊ฐ€ ๋‚จ์•„์žˆ๋Š” ๊ฒฝ์šฐ

        # ๋‘ sub list์˜ ์ฒซ ์›์†Œ๋“ค์„ ๋น„๊ตํ•˜์—ฌ ์ž‘์€ ๊ฒƒ๋ถ€ํ„ฐ result์— ์ถ”๊ฐ€ํ•จ
        if left[0] <= right[0]:
            result.append(left.pop(0))
        else:
            result.append(right.pop(0))

    if len(left) > 0: # ์™ผ์ชฝ list์— ์›์†Œ๊ฐ€ ๋‚จ์•„์žˆ๋Š” ๊ฒฝ์šฐ
        result.extend(left)
    if len(right) > 0: # ์˜ค๋ฅธ์ชฝ list์— ์›์†Œ๊ฐ€ ๋‚จ์•„์žˆ๋Š” ๊ฒฝ์šฐ
        result.extend(right)
    return result


def merge_sort(m):
    if len(m) <= 1: # ๋ฐฐ์—ด ํฌ๊ธฐ๊ฐ€ 0 ์ด๊ฑฐ๋‚˜ 1์ธ ๊ฒฝ์šฐ ๋ฐ”๋กœ return
        return m

    # 1. Divide ๋ถ€๋ถ„
    mid = len(m) // 2
    left = m[:mid]
    right = m[mid:]

    # list์˜ ํฌ๊ธฐ๊ฐ€ 1์ด ๋  ๋•Œ๊นŒ์ง€ merge_sort() ์žฌ๊ท€ ํ˜ธ์ถœ
    left = merge_sort(left)
    right = merge_sort(right)

    # 2. Conquer ๋ถ€๋ถ„ : ๋ถ„ํ• ๋œ ๋ฆฌ์ŠคํŠธ๋“ค ๋ณ‘ํ•จ
    return merge(left, right)

ํ€ต ์ •๋ ฌ (Quick Sort)

  • ์ฃผ์–ด์ง„ ๋ฐฐ์—ด์„ ๋‘ ๊ฐœ๋กœ ๋ถ„ํ• ํ•˜๊ณ , ๊ฐ๊ฐ์„ ์ •๋ ฌํ•œ๋‹ค

  • ๋ณ‘ํ•ฉ ์ •๋ ฌ๊ณผ ๋‹ค๋ฅธ ์ 

    1. ๋ณ‘ํ•ฉ ์ •๋ ฌ์€ ๊ทธ๋ƒฅ ๋‘ ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋ˆ„๋Š” ๋ฐ˜๋ฉด์—, ํ€ต ์ •๋ ฌ์€ ๋ถ„ํ• ํ•  ๋•Œ, ๊ธฐ์ค€ ์•„์ดํ…œ(pivot item) ์ค‘์‹ฌ์œผ๋กœ, ์ด๋ณด๋‹ค ์ž‘์€ ๊ฒƒ์€ ์™ผํŽธ, ํฐ ๊ฒƒ์€ ์˜ค๋ฅธํŽธ์— ์œ„์น˜์‹œํ‚จ๋‹ค

    2. ๊ฐ ๋ถ€๋ถ„ ์ •๋ ฌ์ด ๋๋‚œ ํ›„, ๋ณ‘ํ•ฉ์ •๋ ฌ์„ "๋ณ‘ํ•ฉ"์ด๋ž€ ํ›„์ฒ˜๋ฆฌ ์ž‘์—…์ด ํ•„์š”ํ•˜๋‚˜, ํ€ต ์ •๋ ฌ์€ ํ•„์š”๋กœ ํ•˜์ง€ ์•Š๋Š”๋‹ค.

  • ์‹œ๊ฐ„ ๋ณต์žก๋„

    • nlogn

Hoare-Partition ์•Œ๊ณ ๋ฆฌ์ฆ˜

์•„์ด๋””์–ด

  • P(pivot) ๊ฐ’๋“ค ๋ณด๋‹ค ํฐ ๊ฐ’์€ ์˜ค๋ฅธ์ชฝ, ์ž‘์€ ๊ฐ’๋“ค์€ ์™ผ์ชฝ ์ง‘ํ•ฉ์— ์œ„์น˜ํ•˜๋„๋ก ํ•œ๋‹ค

  • Pivot์„ ๋‘ ์ง‘ํ•ฉ์˜ ๊ฐ€์šด๋ฐ์— ์œ„์น˜์‹œํ‚จ๋‹ค

ํ”ผ๋ด‡ ์„ ํƒ

  • ์™ผ์ชฝ ๋ / ์˜ค๋ฅธ์ชฝ ๋ / ์ž„์˜์˜ ์„ธ ๊ฐœ ๊ฐ’ ์ค‘์— ์ค‘๊ฐ„ ๊ฐ’

ex)

def quick_sort (arr, left, right):
    # pivot ์œ„์น˜ ๊ฒฐ์ • (pivot์„ ๊ธฐ์ค€์œผ๋กœ ํฐ ๊ฐ’์€ ์˜ค๋ฅธ์ชฝ, ์ž‘์€ ๊ฐ’์€ ์™ผ์ชฝ์œผ๋กœ ๊ตฌ๋ถ„)
    # ์™ผ์ชฝ ๋ถ€๋ถ„์ง‘ํ•ฉ ์ •๋ ฌ
    # ์˜ค๋ฅธ์ชฝ ๋ถ€๋ถ„์ง‘ํ•ฉ ์ •๋ ฌ
    if left > right:
        return
    # ํ”ผ๋ด‡ ๊ตฌํ•˜๊ธฐ
    pivot = lomuto_partition(arr, left, right)
    pivot = hoare_partition(arr, left, right)
    # ์™ผ์ชฝ ๋ถ€๋ถ„์ง‘ํ•ฉ ์ •๋ ฌ ์‹คํ–‰
    quick_sort(arr, left, pivot-1)
    # ์˜ค๋ฅด์ชฝ ๋ถ€๋ถ„์ง‘ํ•ฉ ์ •๋ ฌ ์‹คํ–‰
    quick_sort(arr,pivot+1, right)

def lomuto_partition(arr, left, right):
    # ๋งจ ์˜ค๋ฅธ์ชฝ ์š”์†Œ๋ฅผ pivot์œผ๋กœ ์„ค์ •ํ•˜๊ณ ,
    # i = left -1
    # j = left
    pivot = arr[right]
    i = left -1

    for j in range(left, right):
        # arr[i] ๊ฐ€ pivot๋ณด๋‹ค ์ž‘์œผ๋ฉด,
        if arr[j] < pivot:
            # i๋ฅผ 1 ์ฆ๊ฐ€
            # arr[j], arr[i] ์œ„์น˜ ๊ตํ™˜
            i += 1
            arr[i], arr[j] = arr[j], arr[i]

    # i๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ์œ„์น˜๊ฐ€ pivot๋ณด๋‹ค ์ž‘์€ ๊ฐ’์˜ ๋งˆ์ง€๋ง‰ ์ธ๋ฑ์Šค
    # i + 1 ์˜ ์œ„์น˜์— pivot์„ ๋‘๊ณ  i+1 ๋ฐ˜ํ™˜
    arr[i+1], arr[right] = arr[right], arr[i+1]
    
    return i+1

def hoare_partition(arr, left, right):
    # i, j ์„ค์ •ํ•˜๊ณ , ํฐ๊ฐ’ & ์ž‘์€ ๊ฐ’ ์ฐพ์•„์„œ ์œ„์น˜ ๋ฐ”๊ฟ”์ฃผ๊ธฐ
    i = left
    j = right
    pivot = arr[left]

    # i๊ฐ€ j๋ณด๋‹ค ์ž‘์„ ๋•Œ ๊นŒ์ง€ ๊ฒŒ์†ํ•ด์„œ ๋ฐ˜๋ณต
    while i <= j:
        # pivot ๋ณด๋‹ค ํฐ ๊ฐ’์ด ๋‚˜์˜ฌ ๋•Œ ๊นŒ์ง€ i ์ฆ๊ฐ€
        while i<=j and arr[i] <= pivot:
            i += 1
        # pivot ๋ณด๋‹ค ์ž‘์€ ๊ฐ’์ด ๋‚˜์˜ฌ ๋•Œ ๊นŒ์ง€ j ๊ฐ์†Œ
        while i <=j and arr[j] >= pivot:
            j -= 1
        
        # i๊ฐ€ j๋ณด๋‹ค ์ž‘์œผ๋ฉด, ์œ„์น˜ ๊ตํ™˜
        if i < j:
            arr[i], arr[j] = arr[j], arr[i]
    
    arr[left], arr[j] = arr[j], arr[left]
    return j # pivot ์œ„์น˜์ธ j ๋ฐ˜ํ™˜

arr = [4,6,3,6,8,0,3,8,10]
quick_sort(arr, 0, len(arr)-1)
print(arr)

  • ์ž๋ฃŒ์˜ ๊ฐ€์šด๋ฐ์— ์žˆ๋Š” ํ•ญ๋ชฉ์˜ key ๊ฐ’๊ณผ ๋น„๊ตํ•˜์—ฌ ๋‹ค์Œ ๊ฒ€์ƒ‰์˜ ์œ„์น˜๋ฅผ ๊ฒฐ์ •ํ•˜๊ณ  ๊ฒ€์ƒ‰์„ ๊ณ„์† ์ง„ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•

    • ๋ชฉ์  ํ‚ค๋ฅผ ์ฐพ์„ ๋•Œ๊นŒ์ง€ ์ด์ง„ ๊ฒ€์ƒ‰์„ ์ˆœํ™˜์ ์œผ๋กœ ๋ฐ˜๋ณต ์ˆ˜ํ–‰ํ•จ์œผ๋กœ์จ ๊ฒ€์ƒ‰ ๋ฒ”์œ„๋ฅผ ๋ฐ˜์œผ๋กœ ์ค„์—ฌ๊ฐ€๋ฉด์„œ ๋ณด๋‹ค ๋น ๋ฅด๊ฒŒ ๊ฒ€์ƒ‰์„ ์ˆ˜ํ–‰ํ•จ

  • ์ด์ง„ ๊ฒ€์ƒ‰์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ž๋ฃŒ๊ฐ€ ์ •๋ ฌ๋œ ์ƒํƒœ์—ฌ์•ผ ํ•œ๋‹ค.

๊ฒ€์ƒ‰ ๊ณผ์ •

  1. ์ž๋ฃŒ์˜ ์ค‘์•™์— ์žˆ๋Š” ์›์†Œ๋ฅผ ๊ณ ๋ฅธ๋‹ค

  2. ์ค‘์•™ ์›์†Œ์˜ ๊ฐ’๊ณผ ์ฐพ๊ณ ์ž ํ•˜๋Š” ๋ชฉํ‘œ ๊ฐ’์„ ๋น„๊ต

  3. ๋ชฉํ‘œ ๊ฐ’์ด ์ค‘์•™ ์›์†Œ์˜ ๊ฐ’๋ณด๋‹ค

    • ์ž‘์œผ๋ฉด ์ž๋ฃŒ์˜ ์™ผ์ชฝ ๋ฐ˜์— ๋Œ€ํ•ด์„œ ์ƒˆ๋กœ ๊ฒ€์ƒ‰์„ ์ˆ˜ํ–‰

    • ํฌ๋‹ค๋ฉด ์ž๋ฃŒ์˜ ์˜ค๋ฅธ์ชฝ ๋ฐ˜์— ๋Œ€ํ•ด์„œ ์ƒˆ๋กœ ๊ฒ€์ƒ‰์„ ์ˆ˜ํ–‰

  4. ์ฐพ๊ณ ์ž ํ•˜๋Š” ๊ฐ’์„ ์ฐพ์„ ๋•Œ๊นŒ์ง€ 1~3 ๋ฐ˜๋ณต

Last updated