2020-1ํ•™๊ธฐ, ๋Œ€ํ•™์—์„œ โ€˜์•Œ๊ณ ๋ฆฌ์ฆ˜โ€™ ์ˆ˜์—…์„ ๋“ฃ๊ณ  ๊ณต๋ถ€ํ•œ ๋ฐ”๋ฅผ ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค. ์ง€์ ์€ ์–ธ์ œ๋‚˜ ํ™˜์˜์ž…๋‹ˆ๋‹ค :) ์ „์ฒด ํฌ์ŠคํŠธ๋Š” Algorithm ํฌ์ŠคํŠธ์—์„œ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3 minute read

2020-1ํ•™๊ธฐ, ๋Œ€ํ•™์—์„œ โ€˜์•Œ๊ณ ๋ฆฌ์ฆ˜โ€™ ์ˆ˜์—…์„ ๋“ฃ๊ณ  ๊ณต๋ถ€ํ•œ ๋ฐ”๋ฅผ ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค. ์ง€์ ์€ ์–ธ์ œ๋‚˜ ํ™˜์˜์ž…๋‹ˆ๋‹ค :) ์ „์ฒด ํฌ์ŠคํŠธ๋Š” Algorithm ํฌ์ŠคํŠธ์—์„œ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋“ค์–ด๊ฐ€๋ฉฐ

์ž„์˜์˜ ์ˆซ์ž ๋ฐฐ์—ด์ด ์žˆ์„ ๋•Œ $k$๋ฒˆ์งธ๋กœ ์ž‘์€ ๊ฐ’์„ ์ฐพ๋Š” ๊ฒƒ์„ โ€œSelectionโ€์ด๋ผ๊ณ  ํ•œ๋‹ค. ์‰ฝ๊ฒŒ ์ƒ๊ฐํ•˜๋ฉด ๋ฐฐ์—ด์„ ์ •๋ ฌํ•œ ํ›„์— $k$๋ฒˆ์งธ ๊ฐ’์„ ์„ ํƒํ•˜๋ฉด ๋˜์ง€๋งŒ, ํ€ต ์ •๋ ฌ์„ ์“ด๋‹ค๋ฉด ํ‰๊ท  $O(n \log n)$ ์ตœ์•…์˜ ๊ฒฝ์šฐ $O(n^2)$์˜ ๋น„์šฉ์ด ๋“ ๋‹ค. ์ด๋ฒˆ์— ๋‹ค๋ฃฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ โ€œ์ •๋ ฌ๋˜์ง€ ์•Š์€ ๋ฐฐ์—ดโ€์—์„œ $k$๋ฒˆ์งธ๋กœ ์ž‘์€/ํฐ ๊ฐ’์„ ๋น ๋ฅด๊ฒŒ ์ฐพ๋Š” โ€œQuick Selectionโ€์ด๋‹ค. โ€œQuick Selectionโ€์€ $O(n)$์˜ ๋น„์šฉ์œผ๋กœ $k$๋ฒˆ์žฌ ๊ฐ’์„ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค!

Idea

โ€œQuick Selectionโ€์˜ ์•„์ด๋””์–ด๋Š” ํ€ต ์ •๋ ฌ๊ณผ ์ •๋ง ๋น„์Šทํ•˜๋‹ค! โ€œQuick Selectionโ€๋„ pivot์„ ๊ณ ๋ฅด๊ณ  left, center, right๋กœ ๋ฐฐ์—ด์„ ๋ถ„ํ• ํ•œ๋‹ค.

  • input: a list $S$ of numbers and an integer $k$
  • output: The $k$-th smallest elt in $S$

Choose a number $v$ from $S$, split $S$ into 3 sublists w.r.t. $v$.

์ด์ œ $S_L$, $S_v$, $S_R$์˜ ํฌ๊ธฐ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์žฌ๊ท€ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

\[\text{selection}(S, k) = \begin{cases} \text{selection}(S_L, k) & \text{if} \quad k \le \left|S_L\right| \\ v & \text{if} \quad \left| S_L \right| < k \le \left|S_L\right| + \left|S_v\right| \\ \text{selection}(S_R, k - \left|S_L\right| -\left|S_v\right| ) & \text{if} \quad k > \left|S_L\right| + \left|S_v\right| \\ \end{cases}\]

โ€œQuick Selectionโ€ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๊ฐ„๋‹จํ•˜์ง€๋งŒ ๊ฐ•๋ ฅํ•˜๋‹ค ๐Ÿ‘

How to set pivot

โ€œQuick Selectionโ€์˜ ์ฃผ์š”ํ•œ ์ด์Šˆ๋Š” ๊ธฐ์ค€์ด ๋˜๋Š” $v$ ๊ฐ’์„ ์–ด๋–ป๊ฒŒ ์žก๋Š๋ƒ ์ด๋‹ค. ๋งŒ์•ฝ ๋งค ๊ณผ์ •๋งˆ๋‹ค $v$๋ฅผ the smallest elt๋กœ ์žก์œผ๋ฉด ์ตœ์•…์˜ ์ผ€์ด์Šค๋กœ $O(n^2)$์˜ ๋น„์šฉ์ด ๋“ค๊ฒŒ ๋œ๋‹ค.

\[T(n) = T(n-1) + O(n) = O(n^2)\]

์‚ฌ์‹ค ์ข‹์€ pivot์„ ์žก๊ธฐ ์œ„ํ•œ ๋” ๋งŽ์€ ๊ณ ์ฐฐ๋“ค์ด ์žˆ์ง€๋งŒ ์ด๋ฒˆ ํฌ์ŠคํŠธ์—์„œ๋Š” โ€œQuick Selectionโ€์˜ ์•„์ด๋””์–ด๋งŒ ๊ฐ„๋‹จํžˆ ์„ค๋ช…ํ•˜๊ณ  ๋„˜์–ด๊ฐ€๋„๋ก ํ•˜๊ฒ ๋‹ค. pivot์„ ์ž˜ ์žก๊ฒŒ ๋˜๋ฉด $O(n)$์˜ ๋น„์šฉ์ด ๋จ์„ ์ฆ๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค. ์•„๋ž˜์˜ ์•„ํ‹ฐํด์—์„œ ์ด ๋‚ด์šฉ์„ ์ž˜ ๋‹ค๋ฃจ๊ณ  ์žˆ์œผ๋‹ˆ ๋” ๊ถ๊ธˆํ•œ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์ถ”์ฒœํ•œ๋‹ค.

๐Ÿ‘‰ Quick Selection ์•Œ๊ณ ๋ฆฌ์ฆ˜
๐Ÿ‘‰ Median of Medians ์•Œ๊ณ ๋ฆฌ์ฆ˜

Implementation

๋ฆฌํŠธ์ฝ”๋“œ์˜ 215. Kth Largest Element in an Array ๋ฌธ์ œ๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ๋ฌธ์ œ๋ฅผ ํ’€์–ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        # print(sorted(nums))
        mid = len(nums) // 2
        pivot = nums[mid]

        less_list = []
        same_list = []
        more_list = []
        for num in nums:
            if pivot == num:
                same_list.append(num)
            elif pivot < num:
                more_list.append(num)
            else:
                less_list.append(num)

        if len(more_list) >= k:
            return self.findKthLargest(more_list, k)
        elif k <= (len(more_list) + len(same_list)):
            return pivot
        else:
            return self.findKthLargest(less_list, k - (len(more_list) + len(same_list)))

์ฐธ๊ณ ๋กœ C++์—์„œ๋Š” โ€œQuick Selectionโ€์„ ๊ตฌํ˜„ํ•  ํ•„์š”์—†์ด nth_element() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค ๐Ÿ™Œ

Categories:

Updated: