https://leetcode.com/problems/design-browser-history/
이 문제는 브라우저의 방문 기록(뒤로가기, 앞으로가기) 기능을 구현하는 시뮬레이션 문제예요.
직접 클래스를 설계하고, 함수들을 정의해야 하죠.
🧠 문제 요약
브라우저에는 다음과 같은 기능이 있어요:
- 처음 접속하는 홈페이지로 시작
- visit(url): 새로운 페이지 방문 → 현재 위치에서 앞으로 갈 수 있는 기록은 모두 사라짐
- back(steps): 뒤로 steps만큼 감 (더 못 가면 멈춤)
- forward(steps): 앞으로 steps만큼 감 (더 못 가면 멈춤)
- 각 함수는 현재 페이지의 URL을 리턴함
📦 예시 흐름
bh = BrowserHistory("leetcode.com")
bh.visit("google.com") # 현재: google
bh.visit("facebook.com") # 현재: facebook
bh.back(1) # 뒤로: google
bh.back(1) # 뒤로: leetcode
bh.forward(1) # 앞으로: google
bh.visit("youtube.com") # 방문: youtube (facebook 기록 사라짐)
bh.forward(2) # 앞으로 못 감 → youtube
✅ 구현 아이디어
- history: URL들을 저장하는 리스트
- current: 현재 인덱스를 가리키는 포인터
- visit() 호출 시: current 이후를 자르고 새 URL 추가
- back() 호출 시: max(0, current - steps)
- forward() 호출 시: min(len(history) - 1, current + steps)
✅ 예시 코드
class BrowserHistory:
def __init__(self, homepage: str):
self.history = [homepage]
self.current = 0
def visit(self, url: str) -> None:
# 앞으로 가는 기록 제거하고 새 방문
self.history = self.history[:self.current + 1]
self.history.append(url)
self.current += 1
def back(self, steps: int) -> str:
self.current = max(0, self.current - steps)
return self.history[self.current]
def forward(self, steps: int) -> str:
self.current = min(len(self.history) - 1, self.current + steps)
return self.history[self.current]
🎯 시간 복잡도
- visit: O(1) (자르기 연산은 slicing이지만 적절하게 구현 시 효율적)
- back, forward: O(1)
최종 코드
🔁 왜 더블 링크드 리스트인가?
- 앞으로 가기(forward), **뒤로 가기(back)**를 모두 쉽게 하기 위해서예요.
- 단일 연결 리스트(single linked list)는 한 방향으로만 이동 가능하지만,
이중 연결 리스트는 앞/뒤 포인터가 모두 있어서
O(1) 시간에 뒤로도, 앞으로도 움직일 수 있어요.
🧱 구조 설계
class Node:
- val (URL)
- prev (이전 페이지)
- next (다음 페이지)
✅ 코드 구현
class Node:
def __init__(self, val: str):
self.val = val
self.prev = None
self.next = None
class BrowserHistory:
def __init__(self, homepage: str):
self.curr = Node(homepage)
def visit(self, url: str) -> None:
new_node = Node(url)
self.curr.next = new_node
new_node.prev = self.curr
self.curr = new_node # 앞으로 이동
# 앞으로 가는 히스토리는 제거됨 (자동으로 덮어쓰기)
# Python에서는 GC가 알아서 처리
def back(self, steps: int) -> str:
while steps > 0 and self.curr.prev:
self.curr = self.curr.prev
steps -= 1
return self.curr.val
def forward(self, steps: int) -> str:
while steps > 0 and self.curr.next:
self.curr = self.curr.next
steps -= 1
return self.curr.val
🧪 예시 실행 흐름
bh = BrowserHistory("leetcode.com") # 현재: leetcode
bh.visit("google.com") # 현재: google
bh.visit("facebook.com") # 현재: facebook
bh.back(1) # 현재: google
bh.forward(1) # 현재: facebook
🔍 요약
- 장점: 앞으로/뒤로 이동이 O(1)로 가능 (while 루프지만 노드 이동 자체는 빠름)
- 단점: 약간 더 많은 메모리를 사용 (prev 포인터)
'LeetCode > NeetCode' 카테고리의 다른 글
| [카데인 Kadane] 978. Longest Turbulent Subarray ★★★★★ (0) | 2025.04.04 |
|---|---|
| Graph 그래프 이론 (0) | 2025.04.01 |
| 707. Design Linked List (0) | 2025.03.30 |
| 1929. Concatenation of Array (0) | 2025.03.30 |
| 27. Remove Element (0) | 2025.03.30 |