Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[YeomChaeeun] Week 7 #930

Merged
merged 2 commits into from
Jan 25, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions reverse-linked-list/YeomChaeeun.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* 연결 리스트를 뒤집는 알고리즘
* 알고리즘 복잡도
* - 시간 복잡도: O(n)
* - 공간 복잡도: O(n)
*/
/**
* Definition for singly-linked list.
* class ListNode {
* val: number
* next: ListNode | null
* constructor(val?: number, next?: ListNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
* }
*/
function reverseList(head: ListNode | null): ListNode | null {
// console.log(head)
if (head === null || head.next === null) {
return head
}

// 마지막 노드에 도달할 때까지 계속 재귀 호출
const newHead = reverseList(head.next)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

혹시 이 문제를 재귀를 이용해서 푸신 이유를 여쭤볼 수 있을까요? 만약 재귀 대신에 스택과 for문을 함께 사용한다면 공간복잡도가 이론적으로는 O(n) 으로 동일합니다만, 실제로는 재귀 방식이 더 많이 차지할 것 같습니다. (함수의 실행 컨텍스트가 콜스택에 계속해서 쌓이기 떄문에)

image

실제로 위 코드를 스택으로 푼 것과 비교를 위해 돌려봤는데요, 꽤나 큰 차이가 나더라구요. 그래서 재귀로 푸신 이유가 있는지 궁금했습니다.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아, 추가로 아래는 제가 위 메모리 비교 테스트에 쓰인 이전에 스택으로 풀었을 때의 코드인데 혹시 필요하실까봐 첨부드려요!

/**
* Definition for singly-linked list.
* function ListNode(val, next) {
*     this.val = (val===undefined ? 0 : val)
*     this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
   const stack = []

   let temp = head
   while (temp){
       stack.push(temp.val)
       temp = temp.next
   }

   if (!stack.length){
       return null
   }

   const popped = stack.pop()
   const answer = new ListNode(popped)
   
   temp = answer
   while (stack.length > 0){
       const popped = stack.pop()

       temp.next = new ListNode(popped)
       temp = temp.next
   }

   return answer
};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 좋은 방법 알려주셔서 감사합니다! 😊


// 백트래킹 과정
head.next.next = head
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

개인적으로 이 부분이 코드를 읽을 때 직관적이다라는 생각이 들지 않았습니다. 얼핏 읽었을 때 "head 의 다음의 다음 노드가 다시 head?" 인데 확 와닿지는 않더라구요. 그렇다고 재귀로 풀었을 때 더 나은 방법이 있나 생각해보면 또 다른 방법은 잘 떠오르진 않네요!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

앞뒤를 바꿔주는 작업이라고 생각하면 될거같아요 ^^
저도 여러 그림을 그려가며 백트래킹으로 풀어나갔던 것인데 stack도 한번 시도해보겠습니다
감사합니다 👍

head.next = null

return newHead
}
Loading