Week 2-2. [Divide & Conquer] 148. Sort List (Python3)
๋ฌธ์ ํด๊ฒฐ ๊ณผ์
โ๏ธ ๋๋ง์ ๋ฐฉ์์ผ๋ก ๋ฌธ์ ์ ๋ฆฌํ๊ธฐ (=์ฒด๊ณํ)
https://leetcode.com/problems/sort-list/?envType=study-plan-v2&envId=top-interview-150
Sort List - LeetCode
Can you solve this real interview question? Sort List - Given the head of a linked list, return the list after sorting it in ascending order. Example 1: [https://assets.leetcode.com/uploads/2020/09/14/sort_list_1.jpg] Input: head = [4,2,1,3] Output: [1,
leetcode.com
์ฃผ์ด์ง ์ฐ๊ฒฐ๋ฆฌ์คํธ๋ฅผ ์ค๋ฆ์ฐจ์ ์ ๋ ฌํ์ฌ ๋ฐํํ๋ผ.
- ๋ฌธ์ ์ ์ฃผ์ด์ง ํจ์์ ๋ฆฌํด ํ์
์ Optional[ListNode]์ด๋ค.
- ์ด๋ด ๋๋ dummy node๋ฅผ ์ ์ธํ๊ณ ๊ทธ dummy node์ next๋ฅผ ๋ฐํํ๋ฉด ๋๋ค.
- ๋ ธ๋ ๊ฐ์์ ๋ฒ์๋ [0, 5*10^4]์ด๋ค.
- ๋ ธ๋์ ๊ฐ์ ๋ฒ์๋ [-10^5, 10^5]์ด๋ค.
๐ ์ด๋ค ์์ผ๋ก ์ ๊ทผํ๋๊ฐ?
์ฃผ์ด์ง ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ์ํํ์ฌ ์์๋ฅผ ๋ฆฌ์คํธ์ ๋ด๊ณ , ๋ฆฌ์คํธ๋ฅผ ์ ๋ ฌํ ๋ค ๋ค์ ๋ ธ๋๋ก ๋ง๋ค์ด ๋ฐํํ๋ค.
๐ ์๊ณ ๋ฆฌ์ฆ ์ ํ: ์ ๋ ฅ์ ํฌ๊ธฐ๋ฅผ ๋ฐํ์ผ๋ก
linear search์ sort๋ฅผ ์ด์ฉํ๋ค. ์ ๋ ฅ์ ์ต๋๊ฐ 5*10^4
๐ ์์ฌ ์ฝ๋
lst = []
head๊ฐ None์ด ์๋ ๋์:
head.val ๊ฐ์ lst์ ์ถ๊ฐํ๋ค.
lst๋ฅผ ์ค๋ฆ์ฐจ์ ์ ๋ ฌํ๋ค.
ans = cur = ListNode(-1)
x๋ก lst์ ์์๋ฅผ ์ํํ๋ฉด์:
cur.next = ListNode(x)
cur = cur.next
๐ฏ ๊ตฌํ ์ฝ๋
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
lst = []
while head:
lst.append(head.val)
head = head.next
lst.sort()
# ans: ์ ๋ ฌ๋ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ์์ ๋ถ๋ถ์ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ
# cur: ํ์ฌ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๋ ๋ถ๋ถ์ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ
ans = cur = ListNode(-1) # dummy(-1)๋ก ์ด๊ธฐํ
for x in lst:
cur.next = ListNode(x)
cur = cur.next
return ans.next
๋ด ์ฝ๋๋ฅผ ํ๊ตฌํด๋ณด๊ธฐ
โฑ ์ฑ๋ฅ ์ธก์ (์๊ฐ๋ณต์ก๋/๊ณต๊ฐ๋ณต์ก๋)
linear search(O(n))์ sort(O(n log n))๋ฅผ ์ด์ฉํ๋ค. ๋ฐ๋ผ์ ์ ์ฒด ์ฝ๋์ ์๊ฐ ๋ณต์ก๋๋ O(n log n)์ด๋ค.
โ๏ธ ์ฑ๋ฅ ํ๊ณ
1์ด ์ ํ์์ O(n log n)์ ์ต๋ ์ ๋ ฅ์ 10^6~10^7์ด๋ค. ๋ฌธ์ ์์๋ ์ต๋ ์ ๋ ฅ์ด 5*10^4์ด๋ฏ๋ก ์ฑ๋ฅ์ ๊ด์ฐฎ๋ค.
๋ค๋ฅธ ์ฌ๋์ ์ฝ๋๋ฅผ ํ๊ตฌํด๋ณด๊ธฐ
๐ฏ ๊ตฌํ ์ฝ๋
- ์ ์ฝ์กฐ๊ฑด์ ๊ณ ๋ คํ์ ๋ ์์ ์ ์ผ๋ก O(nlogn)์ ์๊ฐ์ ๋ณด์ฅํ๋ ๋ณํฉ์ ๋ ฌ์ ํ์ฉํ์.
- ์ฐ๊ฒฐ๋ฆฌ์คํธ๋ ์ ์ฒด ๊ธธ์ด๋ฅผ ์ ์ ์๊ธฐ ๋๋ฌธ์ ๋ฐ๋ ๊ธฐ๋ฒ์ ํ์ฉํจ์ธ ๋ณ์๋ฅผ ๋ง๋ค์ด, ํ๋์ ๋ณ์๋ ํ ์นธ์ฉ, ๋ค๋ฅธ ๋ณ์๋ ๋ ์นธ์ฉ ์ด๋ํ๋๋ก ํ๋ฉด, ๋ ์นธ์ฉ ์ด๋ํ ๋ณ์๊ฐ ๋ฆฌ์คํธ ๋์ ๋ฟ์ ๋, ํ ์นธ์ฉ ์ด๋ํ ๋ณ์๋ ์ค๊ฐ์ ๋๋ฌํ ๊ฒ
- merge ๊ณผ์ ์ ๋ง์ฝ ๋ ListNode๊ฐ ์กด์ฌํ๋ฉด ๊ฐ์ด ์์ ์ชฝ์ด l1์ผ๋ก ๊ฐ๊ฒ๋ ์นํํ๊ณ l1.next์ ๋ํด ์ฌ๊ทํธ์ถํ์ฌ ํ์ชฝ ListNode๊ฐ None์ด ๋ ๋๊น์ง ํธ์ถํ๋ค. ์ดํ ๋ณํฉ๋ ํํ์ ListNode๊ฐ ๋ฐํ๋๋ฉด ์ฌ๊ท๋ฅผ ์ข ๋ฃํ๋ค.
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if not (head and head.next): return head
# ๋ฐ๋ ๊ธฐ๋ฒ ํ์ฉ
half, slow, fast = None, head, head
while fast and fast.next:
half, slow, fast = slow, slow.next, fast.next.next # slow๋ 1์นธ, fast๋ 2์นธ ์ด๋
half.next = None # ์ฐ๊ฒฐ๋ฆฌ์คํธ ์ฐ๊ฒฐ ๋๊ธฐ
# ๋ถํ ์ฌ๊ท ํธ์ถ
l1 = self.sortList(head)
l2 = self.sortList(slow) # half๋ฅผ ๊ธฐ์ค์ผ๋ก ๋์ ์ฐ๊ฒฐ๋ฆฌ์คํธ์ ์ฒซ ๋ฒ์งธ ๋
ธ๋
return self.mergeTwoLists(l1, l2)
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
if (not l1) or (l2 and l1.val > l2.val):
l1, l2 = l2, l1
if l1: l1.next = self.mergeTwoLists(l1.next, l2)
return l1
โฑ ์ฑ๋ฅ ์ธก์ (์๊ฐ๋ณต์ก๋/๊ณต๊ฐ๋ณต์ก๋)
์ ๋ ฌ ์ฐ์ฌ์ ์๊ฐ๋ณต์ก๋์ ์ํด ๊ฒฐ์ ๋๋ค. ์ ๋ ฌ ์ฐ์ฐ์ ์๊ฐ๋ณต์ก๋๋ ์ต์ O(n log n)์ด๋ค.
๋๋ ์
๋งํฌ๋ ๋ฆฌ์คํธ์์ ๋ณํฉ ์ ๋ ฌ์ ๊ตฌํํ๊ธฐ ์์ง์ ๋ฏ์ค์๋ค. ๋งํฌ๋ ๋ฆฌ์คํธ์์ ๊ฐ์ ๊บผ๋ด ํ์ด์ฌ ๋ด์ฅํจ์๋ฅผ ์ด์ฉํด ์ ๋ ฌํ๋ ์ฝ๋๋ ๊ฐ๋จํ์ง๋ง, ์ง์ ๋ณํฉ ์ ๋ ฌ์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ ๋ํ ์์๋์ด์ผ๊ฒ ๋ค.