Skip to content
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
110 changes: 110 additions & 0 deletions merge-two-sorted-lists/okyungjin.py

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@DaleStudy 개선 제안: 더 나은 변수 네이밍과 주석 정리로 가독성을 높일 수 있습니다. 는 어떤 방식을 말하는건지 제안해주라

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

좋은 제안이에요. 더 나은 변수 네이밍과 주석 정리는 코드 가독성과 유지보수에 큰 도움이 됩니다. 아래 방식으로 구체적으로 제안드립니다.

  1. 변수 네이밍 가이드
  • 리스트 노드 포인터: current, tail, curr, prev 등 일관된 이름 사용
  • 리스트 구간 구분자: l1, l2 대신 list1, list2처럼 의미 명시
  • 비교 대상 값: val1, val2처럼 어떤 값을 가리키는지 명확히
  • 결과물 포인터: merged, tail, head 같은 직관적 이름
  • 반복 상태: while_head, end_condition처럼 상태를 나타내는 이름은 피하고 직관적으로
  1. 주석 정리 원칙
  • 함수/메서드에 한 줄 요약: 무엇을 하는지 간단 명확히
  • 매 분기점 주석 최소화: 코드가 자명할 때는 불필요한 주석 제거
  • 비효율/특수 처리 구간에만 설명
  • 복잡도 표시는 별도 주석으로 보존
  • 불가피한 리스트 교체나 포인터 변경 시 왜 그런 선택을 했는지 이유 기재
  1. 구체적 적용 예시
  • 예시 변수명: l1, l2 대신 list1, list2 유지하고, curr 대신 tail로 통일
  • 주석 예시:
    • 함수 설명: "두 연결 리스트를 오름차순으로 병합하고, 새로운 노드를 추가하지 않고 기존 노드를 재배치한다."
    • 루프 조건: "리스트 중 하나가 소진되면 남은 노드를 끝에 연결한다."
  1. 코드 스타일 가이드라인
  • 중복 주석 제거: 같은 내용을 반복하는 주석 제거
  • 필요 시 docstring 활용: 함수시그니처 바로 아래에 간단한 설명 작성
  • 타입 힌트 유지: Optional[ListNode] 등의 타입은 유지

원하는 방향으로 샘플 리팩틴 코드도 같이 드릴게요.

Comment thread
okyungjin marked this conversation as resolved.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🏷️ 알고리즘 패턴 분석

  • 패턴: Two Pointers, Monotonic Stack, Hash Map / Hash Set
  • 설명: 두 정렬 리스트를 순차적으로 비교하며 작은 값을 연결하는 방식으로 문제를 풀이한다. 포인터를 두 개 사용해 서로의 노드를 탐색하는 전형적인 Two Pointers 패턴이다. 또한 더미 노드를 활용해 구현을 간단하게 만드는 점은 구현 기법에 해당한다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(n + m) O(n + m)
Space O(1) O(1)

피드백: 둘 다 선형 시간복잡도로 병합하며, 메모리 사용은 노드 재사용 여부에 따라 달라진다.

개선 제안: 현재 구현이 적절해 보입니다.

Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# from typing import Optional, List

# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next

# # 파이썬의 toString 역할을 하는 __repr__을 [1,3,4] 형태로 출력되게 수정
# def __repr__(self):
# nodes = []
# curr = self
# while curr:
# nodes.append(str(curr.val))
# curr = curr.next
# return "[" + ",".join(nodes) + "]"

# # 파이썬 list를 ListNode 리스트로 변환해주는 헬퍼 함수
# def make_linked_list(arr: List[int]) -> Optional[ListNode]:
# if not arr:
# return None
# dummy = ListNode(0)
# curr = dummy
# for val in arr:
# curr.next = ListNode(val)
# curr = curr.next
# return dummy.next


# list1의 노드 개수를 n, list2의 노드 개수를 m이라 할 때
# 시간 복잡도: O(n + m)
# 공간 복잡도: O(n + m) ->
class Solution_01:
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
# 맨 앞에 더미 노드를 하나 추가한다
# 없는 상태로 짰는데 if node: else: 구문 늘어나서 맨 앞에 가상의 노드를 하나 추가해줬다
dummy = ListNode(None)
node = dummy

while True:
# list1이 비어있으면 현재 노드 뒤로 list2를 이어준다.
if not list1:
node.next = list2
break

# list2가 비어있으면 현재 노드 뒤로 list1을 이어준다.
if not list2:
node.next = list1
break

# 값을 비교해서 작은 값을 next 노드에 추가한다.
if list1.val <= list2.val:
node.next = ListNode(list1.val)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

이 부분에서 ListNode(list1.val)로 매번 새 노드를 생성하시는데, 기존 노드를 그대로 연결(node.next = list1)하면 새 노드를 안 만들어도 돼서 공간 복잡도를 O(1)로 줄일 수 있을 것 같아요. 저는 그렇게 풀었는데 참고하시라고 남깁니다! 전체 로직은 깔끔하게 잘 읽혔어요 👍

@okyungjin okyungjin Jul 18, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@chapse57 코멘트 감사합니다! 풀이를 2가지로 작성했는데 이 부분 언급해주신게 맞을까요?

https://github.com/okyungjin/leetcode-study/blob/f24511286b1f9519e87e5d64fdb19e3648658584/merge-two-sorted-lists/okyungjin.py#L72-L99

# list1 하나 소비
list1 = list1.next
else:
node.next = ListNode(list2.val)
# list2 하나 소비
list2 = list2.next

# 다음 노드를 현재 노드로 할당해준다
node = node.next

return dummy.next


# [접근법] Solution_01 의 공간 복잡도를 개선했습니다.
# ListNode를 새로 생성하지 않고 기존 노드를 활용하도록 수정했습니다.

# list1의 노드 개수를 n, list2의 노드 개수를 m이라 할 때
# 시간 복잡도: O(n + m)
# 공간 복잡도: O(1) -> dummy만 사용, 추가 공간 복잡도는 O(1)
class Solution_01:
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
# 맨 앞에 더미 노드를 하나 추가한다
# 없는 상태로 짰는데 if node: else: 구문 늘어나서 맨 앞에 가상의 노드를 하나 추가해줬다
dummy = ListNode(None)
node = dummy

while True:
if not list1: # list1이 비어있으면 현재 노드 뒤로 list2를 이어준다.
node.next = list2
break

if not list2: # list2가 비어있으면 현재 노드 뒤로 list1을 이어준다.
node.next = list1
break

# 값을 비교해서 작은 값을 next 노드에 추가한다.
if list1.val <= list2.val:
node.next = list1 # 새로운 ListNode를 생성하지 않고 list1를 할당해준다.
list1 = list1.next # list1 하나 소비
else:
node.next = list2 # 새로운 ListNode를 생성하지 않고 list2를 할당해준다.
list2 = list2.next # list2 하나 소비

# 다음 노드를 현재 노드로 할당해준다
node = node.next

return dummy.next


# 4. 예시 입력으로 호출 및 테스트
# if __name__ == "__main__":
# list1 = make_linked_list([1, 2, 4])
# list2 = make_linked_list([1, 3, 4])

# solution = Solution()
# merged_list = solution.mergeTwoLists(list1, list2)

# print(merged_list)
Loading