공부방/Upstage AI Lab 4기

[Coding] LinkedLists, Listnode

Eddie_D 2024. 12. 27. 17:35

Leetcode를 풀다가 처음 알게된 개념(?).. 유명하고 중요한 개념이라고 하는데 알고리즘이나 코딩을 제대로 배워본 적이 없는 나에게는 넘 생소한 개념이였다. 그래서 이왕 알게된 겸, 블로그에 정리하면서 공부해봄. 

 

Merge two sorted lists

You are given the heads of two sorted linked lists list1 and list2.
Merge the two lists into one sorted list. The list should be made by splicing together the nodes of the first two lists.
Return the head of the merged linked list.

여기서 linked list가 주어진다. 말 그대로 리스트 안의 값들이 서로 연결되어 있는 형태의 리스트이고, 이때 연결은 포인터로 이뤄진다.

ListNode Example:
[value|next] -> [value|next] -> [value|next] -> null

[1|→] -> [2|→] -> [3|→] -> null

 

그리고 아래와 같은 클래스 형식으로 주로 정의되는데, 이때 next에 해당하는 포인터를 조정해서 리스트를 재정렬할 수 있다. 

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val    # The value stored in this node
        self.next = next  # Reference to the next node

 

나는 문제에서 리스트가 이렇게 주어졌길래 리스트의 값들을 직접 노드에 넣고 포인터도 할당해야하나 싶었는데, 그냥 알아서 된다고 한다.

list1 = [1,2,4]  # This is just for showing the values
list2 = [1,3,4]  # This is just for showing the values

# list1 would already be:
# ListNode(1) -> ListNode(2) -> ListNode(4)

# list2 would already be:
# ListNode(1) -> ListNode(3) -> ListNode(4)

def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
    # list1 is already the head (first node) of the first linked list
    # list2 is already the head (first node) of the second linked list
    
    # You can access values like:
    # list1.val  # gives you the first value
    # list1.next.val  # gives you the second value
    # list1.next.next.val  # gives you the third value

리스트에 50개까지 들어간다고 했는데, 그러면 값을 저렇게 .next.next로 호출하는 게 말이 되나? 싶었다.

 

이렇게 하면 길이 상관없이 끝노드까지 갈 수 있다고. 

def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
    # Example of how to traverse a linked list
    current = list1  # Start at the head
    while current is not None:  # Keep going until we hit the end
        print(current.val)  # Do something with the current value
        current = current.next  # Move to next node

 

여기서 또 하나 주의점! head가 있다. 

current = list1 #start at the head 이 줄에 보면 헤드가 있는데 노드에서는 헤드가 중요한 개념인 것 같다.

헤드는 링크드 리스트의 첫 번째 노드를 가르킨다. 즉, 처음 시작점을 의미한다. 

list1 = [1, 2, 4] 가 주어졌을 때 헤드는 1이다. 이렇게 헤드가 1을 가르키면, 다른 리스트의 값과 비교한 뒤에 헤드를 옮겨서, 다음 2를 가르키고, 그런 느낌. 값 자체가 아니고, 위치 정보를 나타내는 포인터 같은 느낌.

list2 = [1, 3, 4]와 합쳐서 순서를 내림차순 정렬을 시킨다면,

빈 더미 리스트를 만들고, list1의 값과 list2의 값을 비교해서 작은 숫자를 더미 리스트에 추가한다.

리스트 둘 중에 하나가 없는 경우나, 한쪽이 먼저 끝나는 경우에 대한 예외 사항도 처리해준다. 

# Definition for singly-linked list

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
        
        
def mergeTwoLists(self, list1: Optional[ListNode], list2:Optional[ListNode]) -> Optional[ListNode]:
    if not list1:
        return list2
    if not list2:
        return list1
    
    dummy = ListNode(0)
    current = dummy
    
    while list1 and list2:
        if list1.val <= list2.val:
            current.next = list1
            list1 = list1.next
        else:
            current.next = list2
            list2 = list2.next
        current = current.next
    
    if list1:
        current.next = list1
    if list2:
        current.next = list2
    
    return dummy.next