[148. Sort List] (알고리즘)
Divide Conquer
문제
Given the head
of a linked list, return the list after sorting it in ascending order.
Example 1:
Input: head = [4,2,1,3] Output: [1,2,3,4]
Example 2:
Input: head = [-1,5,3,4,0] Output: [-1,0,3,4,5]
Example 3:
Input: head = [] Output: []
Constraints:
- The number of nodes in the list is in the range
[0, 5 * 104]
. -105 <= Node.val <= 105
Follow up: Can you sort the linked list in O(n logn)
time and O(1)
memory (i.e. constant space)?
스스로 고민
접근법
- 링크드 리스트에 연결되어 있는 값들을 오름차순으로 정렬하기
의사코드
- 반복문으로 head에 있는 값들은 전부 뽑아냄
- 뽑아낸 값들을 리스트에 넣어줌
- 리스트를 정렬
- 정렬한 리스트 순서대로 다시 링크드 리스트에 넣어줌
구현 코드
# 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]:
list_nums = []
while head != None:
list_nums.append(head.val)
head = head.next
list_nums.sort()
right_list = ListNode(0)
result = right_list
for num in list_nums:
right_list.next = ListNode(num)
right_list = right_list.next
return result.next
시간 복잡도와 공간 복잡도
시간 복잡도:
- 연결 리스트를 반복하여 각 노드의 값을 추출하고 리스트에 추가하는 부분은 O(n) 시간이 걸린다. 여기서 ‘n’은 연결 리스트의 노드 수다.
- 리스트를 정렬하는 부분은 리스트의 길이가 ‘n’일 때 O(nlogn) 시간이 걸린다.
- 정렬된 리스트를 다시 연결 리스트로 변환하는 부분은 O(n) 시간이 걸린다.
따라서 전체 시간 복잡도는 O(n) + O(nlogn) + O(n) = O(nlogn) 다.
공간 복잡도:
- 리스트를 저장하기 위한 list_nums 리스트가 필요하며, 이 리스트의 크기는 입력 연결 리스트의 노드 수와 같다. 따라서 공간 복잡도는 O(n) 다.
- 정렬을 위해 list_nums를 사용하는 것 이외에 추가적인 공간이 필요하지 않으므로 공간 복잡도는 O(n) 다.
총 공간 복잡도는 O(n) 다.
회고 과정
- 솔직히 링크드리스트에 대해서 제대로 이해를 못 한거 같다.
- 이해가 잘 안가는 부분은 프린트로 찍어가면서 이해를 했지만 링크드 리스트 같은 경우 메모리 경로가 나오기 때문에 뭔가 확실한 이해가 잘 안갔다.
list_nums.sort()
right_list = ListNode(0)
result = right_list
for num in list_nums:
right_list.next = ListNode(num)
right_list = right_list.next
return right_list.next
- 위와 같이 하면 반환되는 값이 없다.
- right_list.next 나 result.next나 똑같은거 아닌가 했는데 이 부분이 진짜 이해가 안간다…
- 이해가 갔다!
- result를 새로 선언하는게 이해가 안갔는데 result랑 right_list는 같은 메모리를 참조하고 있다. 그래서 right_list에 순서대로 값을 넣어두면 마지막은 none이 되어있다. 하지만 result는 처음 그대로인 상태이고 첫 값은 0이기 때문에 next를 반환하면 이제 순서대로 값이 나온다.
다른 사람 코드를 보고 그 기준으로 어떤 부분을 개선 할 수 있는지 최종 회고
class Solution:
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
add = []
newhead = head
while head:
add.append(head.val)
head = head.next
add = sorted(add)
print(add)
neww = newhead
for i in add:
newhead.val = i
newhead = newhead.next
return neww
- 다른 사람들의 코드를 보고 이제 링크드 리스트 값이 어떻게 진행되어가는지 좀 더 이해가 잘 되었다.
- 근데 좀 궁금한게 실제로 이렇게 자료구조를 갖는게 DB랑 무슨 상관인지 잘 모르겠어서 좀 찾아 보았다.
- 좀 찾아보니까 실질적으로 DB랑은 상관이 없고 View나 비즈니스 로직에서 사용된다고 한다. 또한 페이지네이션 같은 경우 데이터 베이스 쿼리 결과를 나누고 각 페이지의데이터를 링크드 리스트나 리스트 형태로 표시를 한다고 한다.
- 좀 정리하자면 데이터베이스와 관련있는 부분은 데이터를 가져올 떄 이를 효율적으로 표시하거나 정리하는 데 나타내기 좋으며 DB도 또 다른 세계가 있어서 공부를 따로 해야된다고 한다.
댓글남기기