Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
42 changes: 42 additions & 0 deletions 1472.Design-Browser-History/memo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# 1472. Design Browser History

## step1
まずlistを使ってとく。

step1_del.py: 最初にlistの要素を消去することを考えたが、配列のコピーが発生する

step1_del_v2.py: コピーを防ぐために del を使用

step1_overwrite.py: lengthをクラスで管理する

実行時間的にはstep1_overwrite.pyがもっとも速いが、不要なメモリを解放できることを考えるとstep1_del_v2.pyがもっとも良いと思った。

LinkedListを使ってもとく。この場合はGCによってメモリが自然に解放される。ただし、履歴の移動でO(steps)かかる。

## step2

https://leetcode.com/problems/design-browser-history/solutions/674486/two-stacks-pretty-code-by-interviewrecip-kbz8/

two stackを使った解法。履歴の移動でO(steps)かかる。

以下の問題でも見たことがある。

https://leetcode.com/problems/implement-queue-using-stacks/description/

自分で思いつくことができなかった。

過去と未来を行き来するような状況で発想できるようにしたい。


https://chromium.googlesource.com/chromium/src/+/main/docs/session_history.md

実際のブラウザがどうなっているか少し調べた。

> Chromium tracks the session history of each tab in NavigationController, using a list of NavigationEntry objects to represent the joint session history items. Each frame creates session history items as it navigates. A joint session history item contains the state of each frame of a page at a given point in time, including things like URL, partially entered form data, scroll position, etc.

リストとして管理しているようなので、配列の解法が最も近そう

> Each NavigationEntry uses a tree of FrameNavigationEntries to track this state.

Webページでは内部に複数のiframeがネストされているので、木構造で管理している

26 changes: 26 additions & 0 deletions 1472.Design-Browser-History/step1_del.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
class BrowserHistory:

def __init__(self, homepage: str):
self.history = [homepage]
self.index = 0

def visit(self, url: str) -> None:
self.history = self.history[:self.index + 1]
self.history.append(url)
self.index += 1

def back(self, steps: int) -> str:
self.index = max(0, self.index - steps)
return self.history[self.index]

def forward(self, steps: int) -> str:
self.index = min(len(self.history) - 1, self.index + steps)
return self.history[self.index]



# Your BrowserHistory object will be instantiated and called as such:
# obj = BrowserHistory(homepage)
# obj.visit(url)
# param_2 = obj.back(steps)
# param_3 = obj.forward(steps)
26 changes: 26 additions & 0 deletions 1472.Design-Browser-History/step1_del_v2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
class BrowserHistory:

def __init__(self, homepage: str):
self.history = [homepage]
self.index = 0

def visit(self, url: str) -> None:
del self.history[self.index + 1:]
self.history.append(url)
self.index += 1

def back(self, steps: int) -> str:
self.index = max(0, self.index - steps)
return self.history[self.index]

def forward(self, steps: int) -> str:
self.index = min(len(self.history) - 1, self.index + steps)
return self.history[self.index]



# Your BrowserHistory object will be instantiated and called as such:
# obj = BrowserHistory(homepage)
# obj.visit(url)
# param_2 = obj.back(steps)
# param_3 = obj.forward(steps)
37 changes: 37 additions & 0 deletions 1472.Design-Browser-History/step1_linked_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
class Node:

def __init__(self, val: str):
self.val = val
self.prev = None
self.next = None


class BrowserHistory:

def __init__(self, homepage: str):
self.node = Node(homepage)

def visit(self, url: str) -> None:
next_node = Node(url)
self.node.next = next_node
next_node.prev = self.node
self.node = next_node

def back(self, steps: int) -> str:
while steps > 0 and self.node.prev:
self.node = self.node.prev
steps -= 1
return self.node.val

def forward(self, steps: int) -> str:
while steps > 0 and self.node.next:
self.node = self.node.next
steps -= 1
return self.node.val


# Your BrowserHistory object will be instantiated and called as such:
# obj = BrowserHistory(homepage)
# obj.visit(url)
# param_2 = obj.back(steps)
# param_3 = obj.forward(steps)
30 changes: 30 additions & 0 deletions 1472.Design-Browser-History/step1_overwrite.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
class BrowserHistory:

def __init__(self, homepage: str):
self.history = [homepage]
self.index = 0
self.length = 1

def visit(self, url: str) -> None:
if len(self.history) == self.index + 1:
self.history.append(url)
else:
self.history[self.index + 1] = url
self.index += 1
self.length = self.index + 1

def back(self, steps: int) -> str:
self.index = max(0, self.index - steps)
return self.history[self.index]

def forward(self, steps: int) -> str:
self.index = min(self.length - 1, self.index + steps)
return self.history[self.index]



# Your BrowserHistory object will be instantiated and called as such:
# obj = BrowserHistory(homepage)
# obj.visit(url)
# param_2 = obj.back(steps)
# param_3 = obj.forward(steps)
29 changes: 29 additions & 0 deletions 1472.Design-Browser-History/step2_two_stack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
class BrowserHistory:

def __init__(self, homepage: str):
self.back_stack = [homepage]
self.forward_stack = []

def visit(self, url: str) -> None:
self.back_stack.append(url)
self.forward_stack = []

def back(self, steps: int) -> str:
while steps > 0 and len(self.back_stack) > 1:
self.forward_stack.append(self.back_stack.pop())
steps -= 1
return self.back_stack[-1]

def forward(self, steps: int) -> str:
while steps > 0 and self.forward_stack:
self.back_stack.append(self.forward_stack.pop())
steps -= 1
return self.back_stack[-1]



# Your BrowserHistory object will be instantiated and called as such:
# obj = BrowserHistory(homepage)
# obj.visit(url)
# param_2 = obj.back(steps)
# param_3 = obj.forward(steps)