본문 바로가기
Algorithm/LeetCode

LeetCode - Reverse Linked List 🤦🏻

by HaningYa 2020. 9. 9.
728x90

 


문제

Reverse a singly linked list.

Example:

Input: 1->2->3->4->5->NULL Output: 5->4->3->2->1->NULL

Follow up:

A linked list can be reversed either iteratively or recursively. Could you implement both?


Iteratively - O(N) Time, O(1) Space

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public var val: Int
 *     public var next: ListNode?
 *     public init() { self.val = 0; self.next = nil; }
 *     public init(_ val: Int) { self.val = val; self.next = nil; }
 *     public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; }
 * }
 */
class Solution {
    func reverseList(_ head: ListNode?) -> ListNode? {
        if head?.next == nil {
            return head
        }
        var curr : ListNode? = head
        var prev : ListNode? = nil
        var next : ListNode? = nil
        
        while(curr != nil){
            next = curr?.next //next저장
            curr?.next = prev //reverse
            prev = curr       // advance prev 
            curr = next       // advance curr
        }
        return prev // new head at end
    }
}
  • prev curr next 포인터 선언
  • curr 가 nil 이면 종료
  • next 포인터에 curr.next 할당
  • curr.next와 prev 을 reverse
  • prev 와 curr 앞으로 한단계 진행
  • next는 nil 되도 되고 curr은 nil 되었을때 prev 가 reverse된 리스트의 head가 됨
  • 그래서 return prev

 

 

Recursively - O(N) Time O(N) Space (b/c stack frame)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public var val: Int
 *     public var next: ListNode?
 *     public init() { self.val = 0; self.next = nil; }
 *     public init(_ val: Int) { self.val = val; self.next = nil; }
 *     public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; }
 * }
 */

class Solution {
    func reverseList(_ head: ListNode?) -> ListNode? {
        //연결리스트의 항목이 하나라면 reverse 할 필요가 없기 때문에 바로 head 리턴
        guard let node = head , head?.next != nil else {
            return head
        }
        //연결 리스트의 끝부분 까지 내려간다. (끝에 도착하기 전까지 값 없음)
        //초기에는 제일 끝값이 들어가진다.
        //1->2->3->4->5 의 경우 5에 도달할 때 까지 뒤에 코드는 실행안됨
        var reversedListHead : ListNode? = reverseList(node.next)
        //현재노드(1)의 다음노드(2)의 다음노드값(3)을 현재노드로 바꾼다.
        node.next?.next = node
        //현재노드(1)의 다음노드(2)값을 nil로 바꾼다.
        node.next = nil
        
        //본인이 연결리스트의 마지막일 때 본인을 리턴한다.
        return reversedListHead
    }
}
  • reversedListHead로 연결리스트의 제일 마지막 노드 참조
  • reversedListHead는 연결리스트 마지막 노드 갈 때 까지 return 되지 않음
  • head가 head.next를 주며 뒤에 연결 리스트에게 본인을 뺀 reversed된 리스트 물어봄
  • 그럼 head.next 같은 방식으로 뒤에 연결 리스트에게 reversed 된 리스트 물어봄
  • 이렇게 stack 쌓이다가 base case 가 연결 리스트 한개이기 때문에 본인을 call 한 node 에게 return 된다.
  • 5->4->3->2->1 
  • 4->3->->2->1
  • 3 ->2->1 
  • 2->1 
  • 1 (base case) node.next == nil
  • base case 부터 reversedListHead 쭉쭉 리턴됨
  • 1 다음 노드가 없으니 revresedListHead가 2로 리턴되고 2는 본인과 본인을 뺀 완성된 reversed List를 가지고 있는 셈이다.
  • 그래서 2는 1의 next 를 즉 node가 2 node.next 가 1 node.next.next(1의 화살표) 를 2로 돌리고
  • 2의 next 는 nil로 처리한다. (제일 앞부분일 수 있어서)
  • 그리고 reversedHead를 리턴하므로써 3이 이제 나머지 reversed list 인 2<-1 이랑 작업할 수 있게 한다.

 

 

왜 자꾸 Recursion 은 비동기적으로 생각하는 거지

겁나 헷갈린다.

 

728x90

'Algorithm > LeetCode' 카테고리의 다른 글

LeetCode - Pascal's Triangle II  (0) 2020.09.10
LeetCode - Search in Binary Search Tree  (0) 2020.09.10
LeetCode - Swap Nodes in Pairs  (0) 2020.09.03
LeetCode - Reverse String  (0) 2020.09.03
LeetCode - Largest Time for Given Digits  (0) 2020.09.01

댓글