Skip to content

Commit ea3aa42

Browse files
committedAug 29, 2023
move algorithm repository to TIL
1 parent 410af21 commit ea3aa42

35 files changed

+1088
-4
lines changed
 

‎README.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
11
# TIL
2-
Today I Learned- 매일 보고 들은 모든 것
2+
3+
## Today I Learned- 매일 보고 들은 모든 것
4+
5+
## daily note
6+
7+
## books

‎_dailynote/2023-08-28.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313

1414
실습과 그림으로 배우는 리눅스 구조
1515

16-
- [ch1*컴퓨터*시스템의\_개요](../books/실습과%20그림으로%20배우는%20리눅스%20구조/ch1_컴퓨터_시스템의_개요.md)
17-
- [ch2*사용자*모드로*구현되는*기능](../books/실습과%20그림으로%20배우는%20리눅스%20구조/ch2_사용자_모드로_구현되는_기능.md)
18-
- [ch3*프로세스*관리](../books/실습과%20그림으로%20배우는%20리눅스%20구조/ch3_프로세스_관리.md)
16+
- [ch1 컴퓨터 시스템의 개요](../os/실습과%20그림으로%20배우는%20리눅스%20구조/ch1_컴퓨터_시스템의_개요.md)
17+
- [ch2 사용자 모드로 구현되는 기능](../os/실습과%20그림으로%20배우는%20리눅스%20구조/ch2_사용자_모드로_구현되는_기능.md)
18+
- [ch3 프로세스 관리](../os/실습과%20그림으로%20배우는%20리눅스%20구조/ch3_프로세스_관리.md)
1919

2020
파이썬
2121

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""
2+
link : https://leetcode.com/problems/climbing-stairs/
3+
"""
4+
5+
6+
class Solution:
7+
def cs(self, n):
8+
pass
9+
10+
# top-down(memorization) 방식
11+
12+
def cs_topdown(self, n):
13+
memo = {}
14+
if n == 1:
15+
return 1
16+
if n == 2:
17+
return 2
18+
if n not in memo:
19+
memo[n] = self.cs_topdown(n - 1) + self.cs_topdown(n - 2)
20+
return memo[n]
21+
22+
# bottom-up(tabulation, dp table) 방식
23+
24+
def cs_bottomup(self, n):
25+
memo = {1: 1, 2: 2}
26+
for i in range(3, n + 1):
27+
memo[i] = memo[i - 1] + memo[i - 2]
28+
return memo[n]

‎algorithm/DynamicProgramming/fibo.py

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
def fibo_basic(n):
2+
if n < 3:
3+
return 1
4+
return fibo(n - 1) + fibo(n - 2)
5+
6+
7+
memo = {1: 1, 2: 1}
8+
9+
10+
def fibo_memo(n):
11+
if n in memo:
12+
return memo[n]
13+
memo[n] = fibo(n - 2) + fibo(n - 1)
14+
return memo[n]
15+
16+
17+
def fibo_deco(func):
18+
memo = {1: 1, 2: 1}
19+
20+
def inner(n):
21+
if n in memo:
22+
return memo[n]
23+
memo[n] = func(n)
24+
return memo[n]
25+
26+
return inner
27+
28+
29+
@fibo_deco
30+
def fibo(n):
31+
if n < 3:
32+
return 1
33+
return fibo(n - 1) + fibo(n - 2)
34+
35+
36+
print(fibo(100))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
"""
2+
link: https://leetcode.com/problems/letter-combinations-of-a-phone-number/description/
3+
방법1: digits 길이에 제한이 있다면 사용 불가에 가까움.
4+
방법2 : recursion으로 푸는 방법 추가.
5+
- 그래프 전체를 탐색하는 것과 같음.
6+
"""
7+
from typing import List
8+
9+
10+
class Solution:
11+
def letterCombinations(self, digits: str) -> List[str]:
12+
if digits == "":
13+
return digits
14+
15+
len_digits = len(digits)
16+
num_mapping = {
17+
"2": "abc",
18+
"3": "def",
19+
"4": "ghi",
20+
"5": "jkl",
21+
"6": "mno",
22+
"7": "pqrs",
23+
"8": "tuv",
24+
"9": "wxyz",
25+
}
26+
first = num_mapping[digits[0]] if len_digits > 0 else [""]
27+
second = num_mapping[digits[1]] if len_digits > 1 else [""]
28+
third = num_mapping[digits[2]] if len_digits > 2 else [""]
29+
forth = num_mapping[digits[3]] if len_digits > 3 else [""]
30+
return [
31+
a + b + c + d for a in first for b in second for c in third for d in forth
32+
]
33+
34+
def letterCombinationsRecursion(self, digits: str) -> List[str]:
35+
if not digits:
36+
return []
37+
38+
phone = {
39+
"2": "abc",
40+
"3": "def",
41+
"4": "ghi",
42+
"5": "jkl",
43+
"6": "mno",
44+
"7": "pqrs",
45+
"8": "tuv",
46+
"9": "wxyz",
47+
}
48+
res = []
49+
50+
def backtrack(combination, next_digits):
51+
if not next_digits:
52+
res.append(combination)
53+
return
54+
55+
for letter in phone[next_digits[0]]:
56+
backtrack(combination + letter, next_digits[1:])
57+
58+
backtrack("", digits)
59+
return res

‎algorithm/Graph/graph_bfs.py

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from collections import deque
2+
3+
4+
def bfs(graph, start_v):
5+
visited = [start_v]
6+
queue = deque(start_v)
7+
while queue:
8+
cur_v = queue.popleft()
9+
for v in graph[cur_v]:
10+
if v not in visited:
11+
visited.append(v)
12+
queue.append(v)
13+
return visited
14+
15+
16+
graph = {
17+
"A": ["B", "D", "E"],
18+
"B": ["A", "C", "D"],
19+
"C": ["B"],
20+
"D": ["A", "B"],
21+
"E": ["A"],
22+
}
23+
bfs(graph, "A")
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from typing import List
2+
3+
class Solution:
4+
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
5+
answer=[]
6+
def dfs(elements:List[int], start:int) :
7+
if sum(elements) == target :
8+
answer.append(elements[:])
9+
return
10+
if sum(elements) > target :
11+
return
12+
13+
for i in candidates[start:]:
14+
elements.append(i)
15+
dfs(elements, candidates.index(i))
16+
elements.pop()
17+
dfs([],0)
18+
return answer
19+
20+
def combinationSumFast(self, candidates: List[int], target: int) -> List[List[int]]:
21+
answer=[]
22+
def dfs(csum, index, path) :
23+
if csum == 0:
24+
answer.append(path)
25+
return
26+
if csum < 0 :
27+
return
28+
29+
for i in range(index, len(cantidates)):
30+
dfs(csum-candidates[i], i, path+[candidates[i]])
31+
dfs(target,0,[])
32+
return answer

‎algorithm/Graph/graph_combine.py

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
from typing import List
2+
import itertools
3+
4+
class Solution:
5+
def combineWrong(self, n: int, k: int) -> List[List[int]]:
6+
answer = []
7+
def dfs(combine, elements):
8+
for e in elements :
9+
combine.append(e)
10+
if len(combine) == k :
11+
answer.append(combine[:])
12+
combine.pop()
13+
continue
14+
next_elements = [ i for i in elements if i > e ]
15+
dfs(combine, next_elements)
16+
combine.pop()
17+
18+
elements = [ i for i in range(1, n+1) ]
19+
dfs([],elements)
20+
return answer
21+
22+
def combineDirty(self, n: int, k: int) -> List[List[int]]:
23+
answer = []
24+
def dfs(elements, rest):
25+
for r in rest :
26+
elements.append(r)
27+
if len(elements) == k :
28+
answer.append(elements[:])
29+
elements.pop()
30+
continue
31+
next = [ i for i in rest if i > r ]
32+
dfs(elements, next)
33+
elements.pop()
34+
35+
elements = [ i for i in range(1, n+1) ]
36+
dfs([],elements)
37+
return answer
38+
39+
def combine(self, n:int, k:int) -> List[List[int]]:
40+
answer=[]
41+
def dfs(elements, start: int, k: int):
42+
if k == 0 :
43+
answer.append(elements[:])
44+
return
45+
for i in range(start, n+1):
46+
# elements.append(i)
47+
# dfs(elements, i+1, k-1)
48+
# elements.pop()
49+
dfs(elements+[i], i+1, k-1)
50+
dfs([],1,k)
51+
return answer
52+
53+
def combineTools(self, n, k):
54+
return list(itertools.combinations(range(1,n+1), k))
55+
S=Solution()
56+
print(S.combineWrong(5,3))
57+
# print(S.combine(3,2))
58+
# print(S.combineTools(3,2))

‎algorithm/Graph/graph_dfs.py

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
graph = {
2+
"A": ["B", "D", "E"],
3+
"B": ["A", "C", "D"],
4+
"C": ["B"],
5+
"D": ["A", "B"],
6+
"E": ["A"],
7+
}
8+
visited = []
9+
10+
11+
def dfs(cur_v):
12+
visited.append(cur_v)
13+
for v in graph[cur_v]:
14+
if v not in visited:
15+
dfs(v)
16+
17+
18+
dfs(graph, "A")
19+
20+
21+
def traversal(root):
22+
if root is None:
23+
return
24+
traversal(root.left)
25+
traversal(root.right)
26+
27+
28+
import json
29+
30+
student_data = {}
31+
with open("student_file.json", "w") as f:
32+
json.dump(student_data, f)
33+
34+
with open("student_file.json", "r") as f:
35+
st_python = json.load(f)
36+
37+
# python 메모리에 있는 json fotmat data를 python 객체로 읽기
38+
# 언제쓰나?
39+
st_json = json.dumps(student_data)
40+
st_python2 = json.loads(st_json)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"""
2+
link : https://leetcode.com/problems/longest-consecutive-sequence/
3+
"""
4+
from typing import List
5+
6+
7+
class Solution:
8+
def longest_sequence(nums: List[int]) -> int:
9+
num_dict = {}
10+
count_set = set()
11+
for num in nums:
12+
num_dict[num] = 1
13+
for num in nums:
14+
if num - 1 not in num_dict:
15+
selected = num
16+
count = 1
17+
while selected + 1 in num_dict:
18+
count += 1
19+
selected += 1
20+
count_set.add(count)
21+
# longest = max(longest, count) return longest
22+
return max(count_set) if len(count_set) > 0 else 0
23+
24+
def longest_sequence_sorted(nums: List[int]) -> int:
25+
nums = sorted(nums, reverse=True)
26+
count_set = set()
27+
count = 1
28+
for i in range(1, len(nums)):
29+
if nums[i - 1] == nums[i] + 1:
30+
count += 1
31+
count_set.add(count)
32+
else:
33+
count = 1
34+
return max(count_set) if len(count_set) > 0 else 0
35+
36+
37+
S = Solution
38+
print(S.longest_sequence([100, 4, 200, 1, 3, 2]) == 4)
39+
print(S.longest_sequence_sorted([100, 4, 200, 1, 3, 2]) == 4)
40+
print(
41+
S.longest_sequence([100, 4, 200, 1, 3, 2, 101, 102, 103, 104, 5, 105, 107, 106])
42+
== 8
43+
)
44+
print(S.longest_sequence([100, 4, 200, 1, 10, 14]) == 0)
45+
print(S.longest_sequence_sorted([100, 4, 200, 1, 10, 14]) == 0)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""
2+
link:https://leetcode.com/problems/longest-substring-without-repeating-characters/description/
3+
"""
4+
5+
6+
class Solution:
7+
def lengthOfLongestSubstring(self, s: str) -> int:
8+
length = 0
9+
substring = ""
10+
for i in s:
11+
if i not in substring:
12+
substring += i
13+
length = max(length, len(substring))
14+
else:
15+
idx = substring.find(i)
16+
substring += i
17+
substring = substring[idx + 1 :]
18+
return length
19+
20+
21+
# class Solution:
22+
# def lengthOfLongestSubstring(self, s: str) -> int:
23+
# seen = {}
24+
# l = 0
25+
# output = 0
26+
# for r in range(len(s)):
27+
# if s[r] not in seen:
28+
# output = max(output,r-l+1)
29+
# else:
30+
# if seen[s[r]] < l:
31+
# output = max(output,r-l+1)
32+
# else:
33+
# l = seen[s[r]] + 1
34+
# seen[s[r]] = r
35+
# return output
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"""
2+
link: https://leetcode.com/problems/two-sum/
3+
"""
4+
from typing import List, Union
5+
6+
7+
class Solution:
8+
def two_sum(nums: List[int], target: int) -> Union[List[int], bool]:
9+
memo = {}
10+
for idx, num in enumerate(nums):
11+
if target - num in memo:
12+
return [memo[target - num], idx]
13+
memo[num] = idx
14+
return False
15+
16+
# True False 만 반환해도 될 때
17+
def two_sum_tf(nums: List[int], target: int) -> bool:
18+
memo = {} # dictionary의 목적이 이름에 드러나니 더 좋음
19+
for k in nums:
20+
needed_number = target - k # 변수 따로 선언해서 담아주니까 가독성이 훨씬 좋음
21+
if memo.get(needed_number, None):
22+
return True
23+
memo[k] = 1
24+
return False
25+
26+
27+
S = Solution
28+
print(S.two_sum([4, 1, 9, 7, 5, 3, 16], 13) == [0, 2])
29+
print(S.two_sum([4, 1, 9, 7, 5, 3, 16], 50) is False)
30+
print(S.two_sum([4, 1, 1, 6], 2) == [1, 2])
31+
print(S.two_sum_tf([4, 1, 9, 7, 5, 3, 16], 13) is True)
32+
print(S.two_sum_tf([4, 1, 9, 7, 5, 3, 16], 50) is False)
33+
print(S.two_sum_tf([4, 1, 1, 6], 2) is True)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
"""
2+
link: https://leetcode.com/problems/design-browser-history/
3+
"""
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"""
2+
link : https://leetcode.com/problems/best-time-to-buy-and-sell-stock/description/
3+
"""
4+
from typing import List
5+
6+
7+
class Solution:
8+
def maxProfit(self, prices: List[int]) -> int:
9+
max_profit = 0
10+
min_price = prices[0]
11+
for price in prices:
12+
profit = price - min_price
13+
if profit > max_profit:
14+
max_profit = profit
15+
if price < min_price:
16+
min_price = price
17+
return max_profit
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from typing import List
2+
3+
"""
4+
link: https://leetcode.com/problems/move-zeroes/
5+
use swapping
6+
"""
7+
8+
9+
class Solution:
10+
def moveZeroes(self, nums: list) -> None:
11+
slow = 0
12+
for fast in range(len(nums)):
13+
if nums[fast] != 0 and nums[slow] == 0:
14+
nums[slow], nums[fast] = nums[fast], nums[slow]
15+
16+
# wait while we find a non-zero element to
17+
# swap with you
18+
if nums[slow] != 0:
19+
slow += 1
20+
21+
def moveZeroes_remove(self, nums: List[int]) -> None:
22+
if not any(nums):
23+
return
24+
25+
num_of_zero = 0
26+
while 0 in nums:
27+
nums.remove(0)
28+
num_of_zero += 1
29+
nums.extend([0] * num_of_zero)
30+
31+
32+
s = Solution()
33+
print(s.moveZeroes([0, 0, 0, 0, 0, 0, 0, 0, 0]))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""
2+
link : https://leetcode.com/problems/remove-duplicates-from-sorted-array/
3+
4+
Given an integer array nums sorted in non-decreasing order, remove the duplicates **in-place** such that each unique element appears only once.
5+
The relative order of the elements should be kept the same. Then return the number of unique elements in nums.
6+
7+
**in-place**
8+
입력 크기에 비례하는 추가 공간을 요구하지 않고 입력 데이터 구조 에서 직접 작동하는 알고리즘.
9+
데이터 구조의 별도 복사본을 만들지 않고 입력을 제자리에서 수정함.
10+
=> 별도의 list 만들지 않고 구해라~~
11+
"""
12+
from typing import List
13+
14+
15+
class Solution:
16+
def removeDuplicates(self, nums: List[int]) -> int:
17+
j = 0
18+
for i in range(1, len(nums)):
19+
if nums[j] != nums[i]:
20+
j += 1
21+
nums[j] = nums[i]
22+
return j + 1
23+
24+
25+
s = Solution()
26+
print(s.removeDuplicates([0, 0, 0, 1, 1, 2, 3, 3, 4]) == 5)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"""
2+
Link : https://leetcode.com/problems/search-insert-position/
3+
using binary search for O(log(n)) complexity.
4+
insert 위치 찾는 것은 while 문에 index 끼리 비교하고 index 를 update.
5+
"""
6+
from typing import List
7+
8+
9+
class Solution:
10+
def searchInsert(self, nums: List[int], target: int) -> int:
11+
min_idx, max_idx = 0, len(nums)
12+
while min_idx < max_idx:
13+
cur_idx = (min_idx + max_idx) // 2
14+
if target > nums[cur_idx]:
15+
min_idx = cur_idx + 1
16+
else:
17+
max_idx = cur_idx
18+
return min_idx
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"""
2+
link : https://leetcode.com/problems/single-number-ii/description/
3+
Given an integer array nums where every element appears three times except for one, which appears exactly once. Find the single element and return it.
4+
You must implement a solution with a **linear runtime complexity and use only constant extra space.**
5+
"""
6+
from typing import List
7+
from collections import defaultdict
8+
9+
10+
class Solution:
11+
def singleNumber_no_o1_space(self, nums: List[int]) -> int:
12+
mydict = defaultdict(int)
13+
for i in nums:
14+
mydict[i] = mydict[i] + 1
15+
return list(mydict.keys())[list(mydict.values()).index(1)]
16+
17+
def singleNumber(self, nums: List[int]) -> int:
18+
ones = 0
19+
twos = 0
20+
21+
for num in nums:
22+
ones ^= num & ~twos
23+
twos ^= num & ~ones
24+
25+
return ones
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"""
2+
link: https://leetcode.com/problems/trapping-rain-water/
3+
"""
4+
5+
from typing import List
6+
7+
8+
class Solution:
9+
def trap_two_pointer(self, height: List[int]) -> int:
10+
if not height:
11+
return 0
12+
volume = 0
13+
left, right = 0, len(height) - 1
14+
left_max, right_max = height[left], height[right]
15+
16+
while left < right:
17+
left_max, right_max = max(height[left], left_max), max(
18+
height[right], right_max
19+
)
20+
if left_max <= right_max:
21+
volume += left_max - height[left]
22+
left += 1
23+
else:
24+
volume += right_max - height[right]
25+
right -= 1
26+
return volume
27+
28+
# 스택으로 풀이
29+
def trap_stack(self, height: List[int]) -> int:
30+
stack = []
31+
volume = 0
32+
33+
for i in range(len(height)):
34+
print(stack)
35+
while stack and height[i] > height[stack[-1]]:
36+
top = stack.pop()
37+
38+
if not len(stack):
39+
break
40+
distance = i - stack[-1] - 1
41+
waters = min(height[i], height[stack[-1]]) - height[top]
42+
43+
volume += distance * waters
44+
stack.append(i)
45+
return volume
46+
47+
48+
S = Solution()
49+
print(S.trap_two_pointer([0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]))
50+
print(S.trap_stack([0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]))
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""
2+
link: https://leetcode.com/problems/two-sum/
3+
4+
for 문 두 번 돌지 않고 O(n)으로 풀이
5+
-> remaining 을 구해서 dictionary에 저장하고 찾는 방식. value in dict 는 O(1)연산으로 빨라서 이용할 수 있다면 유리함.
6+
"""
7+
from typing import List
8+
9+
10+
class Solution:
11+
def twoSum(self, nums: List[int], target: int) -> List[int]:
12+
seen = {}
13+
for i, value in enumerate(nums):
14+
remaining = target - nums[i]
15+
16+
if remaining in seen:
17+
return [i, seen[remaining]]
18+
else:
19+
seen[value] = i
20+
21+
22+
s = Solution()
23+
print(s.twoSum([3, 2, 4], 6))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""
2+
link : https://leetcode.com/problems/add-two-numbers
3+
파이썬 알고리즘 인터뷰 참고
4+
"""
5+
6+
7+
class ListNode:
8+
def __init__(self, value=0, next=None):
9+
self.val = value
10+
self.next = next
11+
12+
13+
class Solution:
14+
def add_two_numbers(self, l1: ListNode, l2: ListNode) -> ListNode:
15+
root = head = ListNode(0)
16+
17+
carry = 0
18+
while l1 or l2 or carry:
19+
sum = 0
20+
# 두 입력값의 합 계산
21+
22+
if l1:
23+
sum += l1.val
24+
l1 = l1.next
25+
if l2:
26+
sum += l2.val
27+
l2 = l2.next
28+
29+
# 몫(자리올림수)과 나머지(값) 계산
30+
carry, val = divmod(sum + carry, 10)
31+
head.next = ListNode(val)
32+
head = head.next
33+
34+
return root.next
35+
36+
37+
s = Solution()
38+
print(s.add_two_numbers(l1=[2, 4, 3], l2=[5, 6, 4]))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
"""
2+
link: https://leetcode.com/problems/design-browser-history/
3+
"""
4+
5+
6+
class Site:
7+
def __init__(self, url=0, next=None, previous=None):
8+
self.url = url
9+
self.next = next
10+
self.previous = previous
11+
12+
13+
class BrowserHistory(object):
14+
def __init__(self, url):
15+
self.head = self.current = Site(url=url)
16+
# 아래 처럼 따로 선언하면 Site 가 각각 생성되는 것임. head & current가 같은 객체가 아니게 됨.
17+
# self.head = Site(url=url)
18+
# self.current = Site(url=url)
19+
20+
def visit(self, url):
21+
new_site = Site(url=url, previous=self.current)
22+
self.current.next = new_site
23+
self.current = self.current.next
24+
# current = self.head
25+
# while current.next:
26+
# current = current.next
27+
# current.next = new_site
28+
# self.now = new_site
29+
30+
def back(self, steps):
31+
while steps > 0 and self.current.previous is not None:
32+
steps -= 1
33+
self.current = self.current.previous
34+
# current = self.now
35+
# for _ in range(steps):
36+
# if current.previous:
37+
# current = current.previous
38+
# else:
39+
# self.now = current
40+
# return current
41+
# self.now = current
42+
return self.current.url
43+
44+
def forward(self, steps):
45+
while steps > 0 and self.current.next is not None:
46+
steps -= 1
47+
self.current = self.current.next
48+
# current = self.now
49+
# for _ in range(steps):
50+
# if current.next:
51+
# current = current.next
52+
# else:
53+
# self.now = current
54+
# return current
55+
# self.now = current
56+
return self.current.url
57+
58+
59+
browserHistory = BrowserHistory("google1.com")
60+
browserHistory.visit("google2.com")
61+
browserHistory.visit("google3.com")
62+
browserHistory.visit("google4.com")
63+
browserHistory.visit("google5.com")
64+
browserHistory.visit("google6.com")
65+
browserHistory.visit("google7.com")
66+
browserHistory.visit("google8.com")
67+
browserHistory.visit("google9.com")
68+
browserHistory.visit("google10.com")
69+
print(browserHistory.back(8))
70+
print(browserHistory.forward(4))
71+
browserHistory.visit("google11.com")
72+
browserHistory.visit("google12.com")
73+
print(browserHistory.back(4))
74+
print(browserHistory.forward(1))
75+
print(browserHistory.forward(2))
76+
print(browserHistory.forward(3))
77+
print(browserHistory.forward(4))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"""
2+
Linked List 구현
3+
"""
4+
5+
6+
class Node:
7+
def __init__(self, value=0, next=None):
8+
self.value = value
9+
self.next = next
10+
11+
12+
# first = Node(1)
13+
# second = Node(2)
14+
# third = Node(3)
15+
# first.next = second
16+
# second.next = third
17+
# first.value = 6
18+
19+
20+
class LinkedList(object):
21+
def __init__(self):
22+
self.head = None
23+
self.tail = None
24+
25+
def append(self, value):
26+
new_node = Node(value)
27+
if self.head is None:
28+
self.head = new_node
29+
else:
30+
current = self.head
31+
while current.next:
32+
current = current.next
33+
current.next = new_node
34+
35+
def append_tail(self, value):
36+
new_node = Node(value)
37+
if self.head is None:
38+
self.head = new_node
39+
self.tail = new_node
40+
else:
41+
self.tail.next = new_node
42+
self.tail = self.tail.next
43+
44+
def get(self, idx):
45+
current = self.head
46+
for _ in range(idx):
47+
current = current.next
48+
return current.value
49+
50+
def insert(self, idx, value):
51+
current = self.head
52+
new_node = Node(value)
53+
for _ in range(idx - 1):
54+
current = current.next
55+
new_node.next = current.next
56+
current.next = new_node
57+
58+
def remove(self, idx):
59+
current = self.head
60+
for _ in range(idx - 1):
61+
current = current.next
62+
current.next = current.next.next
63+
64+
65+
ll = LinkedList()
66+
ll.append(1)
67+
ll.append(2)
68+
ll.append(3)
69+
ll.append(4)
70+
ll.insert(2, 9)
71+
print(ll.get(0), ll.get(1), ll.get(2), ll.get(3))
72+
ll.remove(1)
73+
print(ll.get(0), ll.get(1), ll.get(2), ll.get(3))
+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
"""
2+
link: https://leetcode.com/problems/palindrome-linked-list/
3+
파이썬 알고리즘 인터뷰 풀이 참고
4+
런너 기법
5+
- 연결 리스트를 순회할 때 2개의 포인터를 동시에 사용하는 기법
6+
- 한 포인터가 다른 포인터보다 앞서게 하여 병합 지점이나 중간 위치, 길이 등을 판별할 때 유용하게 사용할 수 있다.
7+
- 중간 위치를 찾아내면, 값을 비교하거나 뒤집기를 시도하는 등 활용도가 높다.
8+
9+
"""
10+
import collections
11+
from typing import Deque
12+
13+
14+
class ListNode:
15+
def __init__(self, val=0, next=None):
16+
self.val = val
17+
self.next = next
18+
19+
20+
class Solution:
21+
# 런너를 이용한 풀이
22+
def is_palindrome(self, head: ListNode) -> bool:
23+
rev = None
24+
slow = fast = head
25+
26+
# 런너를 이용해 역순 리스트를 만든다.
27+
# fast 가 두 칸씩 끝까지 가는 동안, slow는 한 칸씩 중간까지 가면서 역순 리스트(rev)를 만든다.
28+
while fast and fast.next:
29+
fast = fast.next.next
30+
rev, rev.next, slow = slow, rev, slow.next
31+
# list node 가 홀수개 일 때, slow를 한 칸 옮겨서 가운데 node를 pass한다.
32+
# fast는 마지막 노드에 있고 fast.next는 None인 것을 이용한다.
33+
if fast:
34+
slow = slow.next
35+
36+
# 팰린드롬 여부 확인
37+
while rev and rev.val == slow.val:
38+
slow, rev = slow.next, rev.next
39+
return not rev
40+
41+
# 데크를 이용한 풀이
42+
def is_palindrome_deque(self, head: ListNode) -> bool:
43+
q: Deque = collections.deque()
44+
45+
if not head:
46+
return True
47+
48+
node = head
49+
while node is not None:
50+
q.append(node.val)
51+
node = node.next
52+
53+
while len(q) > 1:
54+
if q.popleft() != q.pop():
55+
return False
56+
return True
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from typing import List
2+
import heapq
3+
4+
5+
class ListNode:
6+
def __init__(self, value, next):
7+
self.value = value
8+
self.next = next
9+
10+
11+
class Solution:
12+
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
13+
root = result = ListNode(None)
14+
heap = []
15+
16+
# heap 에 모든 연결 리스트의 첫 Node(=루트)를 추가한다.
17+
for i in range(len(lists)):
18+
if lists[i]:
19+
heapq.heappush(heap, (lists[i].val, i, lists[i]))
20+
21+
while heap:
22+
node = heapq.heappop(heap)
23+
idx = node[1]
24+
result.next = node[2]
25+
26+
result = result.next
27+
# linked list 에 다음 원소 있으면 heap에 추가
28+
if result.next:
29+
heapq.heappush(heap, (result.next.val, idx, result.next))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
class CircularQueue:
2+
def __init__(self, k: int):
3+
self.q = [None] * k
4+
self.maxlen = k
5+
self.p1 = 0
6+
self.p2 = 0
7+
8+
# p2(rear) pointer 자리에 값 없는 것 확인 -> 값 추가하고 pointer은 다음으로 이동
9+
def enQueue(self, value: int) -> bool:
10+
if self.q[self.p2] is None:
11+
self.q[self.p2] = value
12+
self.p2 = (self.p2 + 1) % self.maxlen
13+
return True
14+
else:
15+
return False
16+
17+
# p1(front) pointer 자리에 값 있으면 삭제하고 pointer 다음으로 이동
18+
def deQueue(self) -> bool:
19+
if self.q[self.p1] is None:
20+
return False
21+
else:
22+
self.q[self.p1] = None
23+
self.p1 = (self.p1 + 1) % self.maxlen
24+
return True
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
"""
2+
link: https://leetcode.com/problems/daily-temperatures/
3+
"""
4+
5+
6+
class Solution:
7+
def dailyTemperatures(temperatures):
8+
ans = [0] * len(temperatures)
9+
stack = []
10+
for cur_day, cur_temp in enumerate(temperatures):
11+
while stack and stack[-1][1] < cur_temp:
12+
prev_day, _ = stack.pop()
13+
ans[prev_day] = cur_day - prev_day
14+
stack.append((cur_day, cur_temp))
15+
return ans
16+
17+
18+
# TEST
19+
S = Solution
20+
print(S.dailyTemperatures([73, 74, 75, 71, 69, 72, 76, 73]) == [1, 1, 4, 2, 1, 1, 0, 0])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"""
2+
link : https://leetcode.com/problems/valid-parentheses/
3+
"""
4+
5+
6+
class Solution:
7+
def valid_parentheses(s):
8+
stack = []
9+
pair = {"(": ")", "{": "}", "[": "]"}
10+
for e in s:
11+
if e in ["(", "{", "["]:
12+
stack.append(e)
13+
else:
14+
if stack.pop() != pair[e]:
15+
return False
16+
17+
# if len(stack) == 0:
18+
# return True
19+
# else:
20+
# return False
21+
return True if len(stack) == 0 else False
22+
23+
# 다른 코드
24+
def is_valid(s):
25+
stack = []
26+
for p in s:
27+
if p == "(":
28+
stack.append(")")
29+
elif p == "[":
30+
stack.append("]")
31+
elif p == "{":
32+
stack.append("}")
33+
elif not stack or stack.pop() != p:
34+
return False
35+
# return not stack 으로 쓰면 1줄로 줄일 수 있음
36+
return not stack
37+
38+
39+
# TEST
40+
S = Solution()
41+
print(S.is_valid("{({[]})}[]()") is True)
42+
print(S.is_valid("{({[])}[]()") is False)
43+
# print(S.valid_parentheses("{({[]})}[]()"))
44+
# print(S.valid_parentheses("{({[]})}[]()") is True)
45+
# print(S.valid_parentheses("{({[])}[]()") is False)

‎algorithm/Tree/tree_bfs.py

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from typings import List
2+
from collections import deque
3+
4+
5+
def bfs(root) -> List:
6+
visited = []
7+
if root is None:
8+
return 0
9+
q = deque()
10+
q.append(root)
11+
while q:
12+
cur_node = q.popleft()
13+
visited.append(cur_node.value)
14+
15+
if cur_node.left:
16+
q.append(cur_node.left)
17+
if cur_node.right:
18+
q.append(cur_node.right)
19+
return visited

‎algorithm/Tree/tree_dfs.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
def dfs(root):
2+
if root is None:
3+
return
4+
dfs(root.left)
5+
dfs(root.right)
6+
7+
8+
# dfs(root)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
"""
2+
link : https://leetcode.com/problems/maximum-depth-of-binary-tree/
3+
"""
4+
from collections import deque
5+
from typing import Optional
6+
7+
8+
# Definition for a binary tree node.
9+
class TreeNode:
10+
def __init__(self, val=0, left=None, right=None):
11+
self.val = val
12+
self.left = left
13+
self.right = right
14+
15+
16+
def array2tree(arr):
17+
q = deque()
18+
root = TreeNode(arr[0])
19+
q.append(root)
20+
21+
idx = 1
22+
while idx < len(arr):
23+
cur_node = q.popleft()
24+
25+
# left Node
26+
if arr[idx] is not None:
27+
cur_node.left = TreeNode(arr[idx])
28+
q.append(cur_node.left)
29+
idx += 1
30+
31+
# right Node
32+
if arr[idx] is not None:
33+
cur_node.right = TreeNode(arr[idx])
34+
q.append(cur_node.right)
35+
idx += 1
36+
return root
37+
38+
39+
class Solution:
40+
def max_depth(self, root: Optional[TreeNode]) -> int:
41+
max_depth = 0
42+
if root is None:
43+
return max_depth
44+
q = deque()
45+
q.append((root, 1))
46+
while q:
47+
cur_node, cur_depth = q.popleft()
48+
max_depth = cur_depth
49+
if cur_node.left:
50+
q.append((cur_node.left, cur_depth + 1))
51+
if cur_node.right:
52+
q.append((cur_node.right, cur_depth + 1))
53+
pass
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
"""
2+
link : https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/description/
3+
"""
4+
from collections import deque
5+
6+
7+
# Definition for a binary tree node.
8+
class TreeNode:
9+
def __init__(self, val=0):
10+
self.val = val
11+
self.left = None
12+
self.right = None
13+
14+
15+
def array2tree(arr):
16+
q = deque()
17+
root = TreeNode(arr[0])
18+
q.append(root)
19+
20+
idx = 1
21+
while idx < len(arr):
22+
cur_node = q.popleft()
23+
24+
# left Node
25+
if arr[idx] is not None:
26+
cur_node.left = TreeNode(arr[idx])
27+
q.append(cur_node.left)
28+
idx += 1
29+
30+
# right Node
31+
if arr[idx] is not None:
32+
cur_node.right = TreeNode(arr[idx])
33+
q.append(cur_node.right)
34+
idx += 1
35+
return root
36+
37+
38+
class Solution:
39+
def lowest_common_ancestor(self, root, p, q):
40+
if root is None:
41+
return None
42+
left = self.lowest_common_ancestor(root.left, p, q)
43+
right = self.lowest_common_ancestor(root.right, p, q)
44+
if root.val == p or root.val == q:
45+
return root.val
46+
elif left and right:
47+
return root.val
48+
return left or right
49+
50+
51+
S = Solution()
52+
root = array2tree([3, 5, 1, 6, 0, 8, 9, None, None, 7, 4])
53+
print(S.lowest_common_ancestor(root, 6, 4) == 5)

0 commit comments

Comments
 (0)
Please sign in to comment.