From 5f928c3d938c0b44930b0b392a1ba19204de8894 Mon Sep 17 00:00:00 2001
From: Jay Mo <115325888+Jay-Mo-99@users.noreply.github.com>
Date: Fri, 17 Jan 2025 14:06:40 -0500
Subject: [PATCH 01/17] Create README - LeetHub
---
.../README.md | 41 +++++++++++++++++++
1 file changed, 41 insertions(+)
create mode 100644 0211-design-add-and-search-words-data-structure/README.md
diff --git a/0211-design-add-and-search-words-data-structure/README.md b/0211-design-add-and-search-words-data-structure/README.md
new file mode 100644
index 000000000..d13e67b18
--- /dev/null
+++ b/0211-design-add-and-search-words-data-structure/README.md
@@ -0,0 +1,41 @@
+
Medium
Design a data structure that supports adding new words and finding if a string matches any previously added string.
+
+Implement the WordDictionary
class:
+
+
+ WordDictionary()
Initializes the object.
+ void addWord(word)
Adds word
to the data structure, it can be matched later.
+ bool search(word)
Returns true
if there is any string in the data structure that matches word
or false
otherwise. word
may contain dots '.'
where dots can be matched with any letter.
+
+
+
+Example:
+
+
+Input
+["WordDictionary","addWord","addWord","addWord","search","search","search","search"]
+[[],["bad"],["dad"],["mad"],["pad"],["bad"],[".ad"],["b.."]]
+Output
+[null,null,null,null,false,true,true,true]
+
+Explanation
+WordDictionary wordDictionary = new WordDictionary();
+wordDictionary.addWord("bad");
+wordDictionary.addWord("dad");
+wordDictionary.addWord("mad");
+wordDictionary.search("pad"); // return False
+wordDictionary.search("bad"); // return True
+wordDictionary.search(".ad"); // return True
+wordDictionary.search("b.."); // return True
+
+
+
+Constraints:
+
+
+ 1 <= word.length <= 25
+ word
in addWord
consists of lowercase English letters.
+ word
in search
consist of '.'
or lowercase English letters.
+ - There will be at most
2
dots in word
for search
queries.
+ - At most
104
calls will be made to addWord
and search
.
+
From 8006e875c83e200c1c551f985fde5d190b6fac37 Mon Sep 17 00:00:00 2001
From: Jay Mo <115325888+Jay-Mo-99@users.noreply.github.com>
Date: Fri, 17 Jan 2025 14:06:40 -0500
Subject: [PATCH 02/17] Time: 1514 ms (25.2%), Space: 68 MB (13.71%) - LeetHub
---
...ign-add-and-search-words-data-structure.py | 42 +++++++++++++++++++
1 file changed, 42 insertions(+)
create mode 100644 0211-design-add-and-search-words-data-structure/0211-design-add-and-search-words-data-structure.py
diff --git a/0211-design-add-and-search-words-data-structure/0211-design-add-and-search-words-data-structure.py b/0211-design-add-and-search-words-data-structure/0211-design-add-and-search-words-data-structure.py
new file mode 100644
index 000000000..32d7d8d52
--- /dev/null
+++ b/0211-design-add-and-search-words-data-structure/0211-design-add-and-search-words-data-structure.py
@@ -0,0 +1,42 @@
+class Node:
+
+ def __init__(self):
+
+ self.d = defaultdict(Node)
+ self.EOW = False
+
+
+class WordDictionary:
+
+ def __init__(self):
+ self.words = Node()
+
+
+ def addWord(self, word: str) -> None:
+
+ cur = self.words
+ for ch in word: cur = cur.d[ch]
+ cur.EOW = True
+
+
+ def search(self, word: str) -> bool:
+
+ return self.dfs(word, self.words)
+
+
+ def dfs(self, word: str, node: Node, i = 0) -> bool:
+
+ if not node : return False
+ if i == len(word) : return node.EOW
+
+ if word[i] == '.' : return any(
+ (self.dfs(word, child, i+1)
+ for child in node.d.values()))
+
+ return self.dfs(word, node.d.get(word[i]), i+1)
+
+
+# Your WordDictionary object will be instantiated and called as such:
+# obj = WordDictionary()
+# obj.addWord(word)
+# param_2 = obj.search(word)
\ No newline at end of file
From b2c0bb95b960fa43286e342904b9a64ccd3f723e Mon Sep 17 00:00:00 2001
From: Jay Mo <115325888+Jay-Mo-99@users.noreply.github.com>
Date: Fri, 17 Jan 2025 14:23:50 -0500
Subject: [PATCH 03/17] Time: 1514 ms (25.2%), Space: 68 MB (13.71%) - LeetHub
From 3872b70ff4dd638a71ac39d73fd6b6c8f674d8ce Mon Sep 17 00:00:00 2001
From: Jay Mo <115325888+Jay-Mo-99@users.noreply.github.com>
Date: Fri, 17 Jan 2025 14:25:21 -0500
Subject: [PATCH 04/17] Time: 1095 ms (82.99%), Space: 65.5 MB (43.88%) -
LeetHub
---
...ign-add-and-search-words-data-structure.py | 58 ++++++++-----------
1 file changed, 25 insertions(+), 33 deletions(-)
diff --git a/0211-design-add-and-search-words-data-structure/0211-design-add-and-search-words-data-structure.py b/0211-design-add-and-search-words-data-structure/0211-design-add-and-search-words-data-structure.py
index 32d7d8d52..158dba2ba 100644
--- a/0211-design-add-and-search-words-data-structure/0211-design-add-and-search-words-data-structure.py
+++ b/0211-design-add-and-search-words-data-structure/0211-design-add-and-search-words-data-structure.py
@@ -1,42 +1,34 @@
-class Node:
-
+class TrieNode:
def __init__(self):
-
- self.d = defaultdict(Node)
- self.EOW = False
-
+ self.children = {}
+ self.is_end_of_word = False
class WordDictionary:
-
def __init__(self):
- self.words = Node()
-
+ self.root = TrieNode()
def addWord(self, word: str) -> None:
-
- cur = self.words
- for ch in word: cur = cur.d[ch]
- cur.EOW = True
-
+ node = self.root
+ for char in word:
+ if char not in node.children:
+ node.children[char] = TrieNode()
+ node = node.children[char]
+ node.is_end_of_word = True
def search(self, word: str) -> bool:
+ def dfs(index, node):
+ if index == len(word):
+ return node.is_end_of_word
+
+ char = word[index]
+ if char == '.':
+ for child in node.children.values():
+ if dfs(index + 1, child):
+ return True
+ return False
+ else:
+ if char not in node.children:
+ return False
+ return dfs(index + 1, node.children[char])
- return self.dfs(word, self.words)
-
-
- def dfs(self, word: str, node: Node, i = 0) -> bool:
-
- if not node : return False
- if i == len(word) : return node.EOW
-
- if word[i] == '.' : return any(
- (self.dfs(word, child, i+1)
- for child in node.d.values()))
-
- return self.dfs(word, node.d.get(word[i]), i+1)
-
-
-# Your WordDictionary object will be instantiated and called as such:
-# obj = WordDictionary()
-# obj.addWord(word)
-# param_2 = obj.search(word)
\ No newline at end of file
+ return dfs(0, self.root)
From 6f7f35e210fab2e433f882f693769cb6dff34c83 Mon Sep 17 00:00:00 2001
From: unknown
Date: Fri, 17 Jan 2025 19:40:52 -0500
Subject: [PATCH 05/17] Analyze design and search words data structure
---
.../Jay-Mo-99.py | 120 ++++++++++++++++++
1 file changed, 120 insertions(+)
create mode 100644 design-add-and-search-words-data-structure/Jay-Mo-99.py
diff --git a/design-add-and-search-words-data-structure/Jay-Mo-99.py b/design-add-and-search-words-data-structure/Jay-Mo-99.py
new file mode 100644
index 000000000..3de11a1bd
--- /dev/null
+++ b/design-add-and-search-words-data-structure/Jay-Mo-99.py
@@ -0,0 +1,120 @@
+# 해석
+# 0. TrieNode 클래스 정의:
+# - 각 TrieNode 인스턴스는 다음의 두 가지 속성을 가진다:
+# 1) children: 현재 노드의 자식 노드들을 저장하는 딕셔너리 (문자 -> TrieNode 인스턴스).
+# 2) is_end_of_word: 현재 노드가 단어의 끝인지 나타내는 Boolean 값.
+
+# 1. WordDictionary 클래스 정의:
+# - WordDictionary 클래스는 Trie 자료구조를 사용하여 단어를 저장(addWord)하고 탐색(search)한다.
+
+# 1-1. __init__ 함수:
+# - root는 TrieNode 클래스로 생성된 인스턴스를 가진다.
+# - Trie 자료구조의 시작점(루트 노드) 역할을 한다.
+
+# 1-2. addWord 함수:
+# 1) 루트 노드(self.root)에서 시작.
+# 2) 단어의 각 문자를 순회하며:
+# - 현재 노드의 children에 문자가 없으면, 새 TrieNode를 생성해 추가.
+# - 현재 노드를 해당 문자의 자식 노드로 이동.
+# 3) 단어의 마지막 문자를 처리한 후, 해당 노드의 is_end_of_word를 True로 설정.
+
+
+# 1-3. search 함수:
+# - 주어진 단어가 Trie에 존재하는지 확인하는 함수.
+# - 와일드카드 문자(.)를 처리할 수 있다.
+# - 내부적으로 dfs(깊이 우선 탐색) 함수를 사용하여 트라이를 탐색.
+# - dfs(index, node):
+# 1) 종료 조건: index가 단어 길이에 도달하면, 현재 노드의 is_end_of_word 반환.
+# 2) 현재 문자가 '.'인 경우:
+# - 현재 노드의 모든 자식 노드에 대해 dfs를 호출.
+# - 하나라도 True를 반환하면 True 반환.
+# 3) 현재 문자가 일반 문자인 경우:
+# - 자식 노드에 문자가 없으면 False 반환.
+# - 자식 노드로 이동해 dfs를 재귀 호출.
+
+
+
+ #Big O
+ # - N: 저장된 모든 단어의 총 문자 수 (Trie에 저장된 모든 문자의 개수).
+ # - C: 알파벳의 개수 (영어 기준 최대 26).
+
+ #Time Complexity: O(N)
+ #- addWord함수 : N에 기반하여 단어 추가
+ #- searchWord 함수:
+ # - 일반 탐색: O(n), n은 단어의 길이.
+ # - 와일드카드 탐색: 최악의 경우 O(C^N),
+ # - C는 알파벳 개수 (최대 26).
+ # - N은 단어의 길이. 와일드카드 문자가 많을수록 모든 경로를 탐색해야 할 수도 있음.
+
+ # - Space Complexity: O(N × C)
+ #
+ # - 각 노드는:
+ # 1) children 딕셔너리를 통해 자식 노드를 저장 (메모리 사용).
+ # 2) is_end_of_word 변수 (Boolean 값, O(1)).
+ # - Trie에 저장된 단어의 문자 수가 많을수록 메모리 사용량 증가.
+
+class TrieNode:
+ def __init__(self):
+ self.children = {} #알파벳 a부터 z까지를 자식으로 가짐, 크기 26의 배열이나 딕셔너리를 사용.
+ self.is_end_of_word = False #어떤 단어의 끝인지 나타내는 Boolean 값
+ #예를 들어, "note"이라는 단어의 'e'에 해당하는 노드의 is_end_of_word가 True, 'n'
+
+class WordDictionary:
+ def __init__(self):
+ self.root = TrieNode() # WD로 생성된 인스턴스.root = TrieNode 인스턴스
+
+ def addWord(self, word: str) -> None:
+ node = self.root #node에 self.root를 부여
+ for char in word: # 매개변수 word를 하나씩 순회하며 char에 저장 (예: word="note" -> char="n", "o", "t", "e")
+ if char not in node.children: # 만약 char가 현재 노드의 자식 노드 목록에 없다면
+ node.children[char] = TrieNode()
+ #node.children[char]을 TrideNode 인스턴스로 생성
+ # self.root.children = {
+ # "n": TrieNode() # "n" 키가 추가되고, 값으로 새로운 TrieNode 인스턴스가 들어감
+ # }
+
+ #Example1:
+ #root
+ #└── "n" (children={}, is_end_of_word=False)
+
+ #Example2:
+ #└── "n" (children={}, is_end_of_word=False)
+ # └── "o" (children={}, is_end_of_word=False)
+ node = node.children[char] #node를 현 node의 children[char]로 이동
+ #Example1:
+ # node = node.children["n"]
+
+ #Example2:
+ # node = node.children["o"]
+ node.is_end_of_word = True
+ #After for loop, 끝 노드의 is_end_of_word를 True로 전환
+
+ #Example 4:
+ #root
+ #└── "n"
+ #└── "o"
+ #└── "t"
+ #└── "e" (children={}, is_end_of_word=True)
+
+ def search(self, word: str) -> bool:
+ def dfs(index, node): # DFS 함수 정의
+ # 1) 종료 조건: 모든 문자를 탐색한 경우
+ if index == len(word):
+ return node.is_end_of_word # 단어 끝 여부 반환
+ # 2) 현재 문자 처리
+ char = word[index]
+ if char == '.': # 2-1) 와일드카드인 경우
+ for child in node.children.values(): # 모든 자식 노드 탐색
+ if dfs(index + 1, child): #dfs를 재귀호출 하여 다음 노드로 탐색 재개
+ return True #재귀 이후에 있으면 True
+ return False #없으면 False
+ else: # 2-2) 일반 문자 처리
+ if char not in node.children: # 현재 문자가 자식 노드에 없는 경우 False
+ return False
+ return dfs(index + 1, node.children[char]) # 다음 노드로 이동하여 탐색
+
+ return dfs(0, self.root)
+ #1. def dfs를 self.root 위치에서 첫 호출.
+
+
+
From aa1a1accc011dd9a07c6a9346a7c0e3057837864 Mon Sep 17 00:00:00 2001
From: Jay Mo <115325888+Jay-Mo-99@users.noreply.github.com>
Date: Tue, 21 Jan 2025 21:39:13 -0500
Subject: [PATCH 06/17] Create README - LeetHub
---
0206-reverse-linked-list/README.md | 34 ++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
create mode 100644 0206-reverse-linked-list/README.md
diff --git a/0206-reverse-linked-list/README.md b/0206-reverse-linked-list/README.md
new file mode 100644
index 000000000..d0e5a2292
--- /dev/null
+++ b/0206-reverse-linked-list/README.md
@@ -0,0 +1,34 @@
+Easy
Given the head
of a singly linked list, reverse the list, and return the reversed list.
+
+
+Example 1:
+
+
+Input: head = [1,2,3,4,5]
+Output: [5,4,3,2,1]
+
+
+Example 2:
+
+
+Input: head = [1,2]
+Output: [2,1]
+
+
+Example 3:
+
+
+Input: head = []
+Output: []
+
+
+
+Constraints:
+
+
+ - The number of nodes in the list is the range
[0, 5000]
.
+ -5000 <= Node.val <= 5000
+
+
+
+Follow up: A linked list can be reversed either iteratively or recursively. Could you implement both?
From 67c6eb000cbe0d2bba59a069490e8514ea003412 Mon Sep 17 00:00:00 2001
From: Jay Mo <115325888+Jay-Mo-99@users.noreply.github.com>
Date: Tue, 21 Jan 2025 21:39:14 -0500
Subject: [PATCH 07/17] Time: 2 ms (19.04%), Space: 16 MB (14.06%) - LeetHub
---
.../0206-reverse-linked-list.py | 26 +++++++++++++++++++
1 file changed, 26 insertions(+)
create mode 100644 0206-reverse-linked-list/0206-reverse-linked-list.py
diff --git a/0206-reverse-linked-list/0206-reverse-linked-list.py b/0206-reverse-linked-list/0206-reverse-linked-list.py
new file mode 100644
index 000000000..b48bb838b
--- /dev/null
+++ b/0206-reverse-linked-list/0206-reverse-linked-list.py
@@ -0,0 +1,26 @@
+# Definition for singly-linked list.
+# class ListNode(object):
+# def __init__(self, val=0, next=None):
+# self.val = val
+# self.next = next
+class Solution(object):
+ def reverseList(self, head):
+ """
+ :type head: Optional[ListNode]
+ :rtype: Optional[ListNode]
+ """
+ temp =[]
+ while head:
+ temp.append(head.val)
+ head = head.next
+
+ temp = temp[::-1] #Reverse the temp list
+
+ myNode = ListNode() #Create the Listnode instance
+ current = myNode
+
+ for value in temp:
+ current.next = ListNode(value)
+ current = current.next
+
+ return myNode.next
From 63ce3fdd8b964a09744b928ec2e529b996a1b09d Mon Sep 17 00:00:00 2001
From: unknown
Date: Tue, 21 Jan 2025 22:44:05 -0500
Subject: [PATCH 08/17] Solve: reverse linked list
---
reverse-linked-list/Jay-Mo-99.py | 48 ++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
create mode 100644 reverse-linked-list/Jay-Mo-99.py
diff --git a/reverse-linked-list/Jay-Mo-99.py b/reverse-linked-list/Jay-Mo-99.py
new file mode 100644
index 000000000..727884465
--- /dev/null
+++ b/reverse-linked-list/Jay-Mo-99.py
@@ -0,0 +1,48 @@
+ #해석
+ # 매개변수 head (ListNode 클래스의 인스턴스)에서 값을 추출하여 temp 리스트에 저장한다.
+ # temp 리스트를 역순으로 정렬(reverse)하여 연결 리스트를 뒤집는다.
+ # temp 리스트의 각 값을 ListNode 클래스를 사용해 새 연결 리스트(myNode)를 생성하며 순서대로 추가한다.
+ # 최종적으로 myNode의 next를 반환한다(이것은 새 연결 리스트의 시작점을 가리킨다).
+
+
+ #Big O
+ #- N: 입력 연결 리스트(head)의 노드 갯수
+
+ #Time Complexity: O(N)
+ #- while head: 연결 리스트의 모든 노드를 순회하며 val을 temp에 저장하므로 O(N).
+ #- for value in temp: temp 리스트의 모든 값을 순회하며 새로운 노드를 생성하므로 O(N).
+
+ #Space Complexity: O(N)
+ #- temp : 연결 리스트의 모든 val을 저장하므로 O(N).
+ #- myNode 인스턴스: for loop 동안 current.next에 ListNode 인스턴스를 생성한다. 이 작업은 O(1) 작업이 N번 반복되므로 O(N).
+
+
+# Definition for singly-linked list.
+# class ListNode(object):
+# def __init__(self, val=0, next=None):
+# self.val = val
+# self.next = next
+class Solution(object):
+ def reverseList(self, head):
+ """
+ :type head: Optional[ListNode]
+ :rtype: Optional[ListNode]
+ """
+ temp =[]
+ while head:
+ temp.append(head.val)
+ head = head.next
+
+ temp = temp[::-1] #Reverse the temp list
+
+ myNode = ListNode() #Create the Listnode instance
+ current = myNode #Update current to myNode for Initialize
+
+ for value in temp:
+ current.next = ListNode(value) ## Create new ListNode Instance and assign it to current.next ,
+ current = current.next #Move to the current.next(new Instance base on ListNode )
+
+ return myNode.next ## Return the head of the newly created linked list
+
+
+
From d13ff9e0c1e1849be274d3e547d1ed5c5843c917 Mon Sep 17 00:00:00 2001
From: Jay Mo <115325888+Jay-Mo-99@users.noreply.github.com>
Date: Tue, 21 Jan 2025 23:00:14 -0500
Subject: [PATCH 09/17] Delete
0211-design-add-and-search-words-data-structure/README.md
---
.../README.md | 41 -------------------
1 file changed, 41 deletions(-)
delete mode 100644 0211-design-add-and-search-words-data-structure/README.md
diff --git a/0211-design-add-and-search-words-data-structure/README.md b/0211-design-add-and-search-words-data-structure/README.md
deleted file mode 100644
index d13e67b18..000000000
--- a/0211-design-add-and-search-words-data-structure/README.md
+++ /dev/null
@@ -1,41 +0,0 @@
-Medium
Design a data structure that supports adding new words and finding if a string matches any previously added string.
-
-Implement the WordDictionary
class:
-
-
- WordDictionary()
Initializes the object.
- void addWord(word)
Adds word
to the data structure, it can be matched later.
- bool search(word)
Returns true
if there is any string in the data structure that matches word
or false
otherwise. word
may contain dots '.'
where dots can be matched with any letter.
-
-
-
-Example:
-
-
-Input
-["WordDictionary","addWord","addWord","addWord","search","search","search","search"]
-[[],["bad"],["dad"],["mad"],["pad"],["bad"],[".ad"],["b.."]]
-Output
-[null,null,null,null,false,true,true,true]
-
-Explanation
-WordDictionary wordDictionary = new WordDictionary();
-wordDictionary.addWord("bad");
-wordDictionary.addWord("dad");
-wordDictionary.addWord("mad");
-wordDictionary.search("pad"); // return False
-wordDictionary.search("bad"); // return True
-wordDictionary.search(".ad"); // return True
-wordDictionary.search("b.."); // return True
-
-
-
-Constraints:
-
-
- 1 <= word.length <= 25
- word
in addWord
consists of lowercase English letters.
- word
in search
consist of '.'
or lowercase English letters.
- - There will be at most
2
dots in word
for search
queries.
- - At most
104
calls will be made to addWord
and search
.
-
From 784e9b6b97cb74c01d8cc79e99b72e6fe408ea3c Mon Sep 17 00:00:00 2001
From: Jay Mo <115325888+Jay-Mo-99@users.noreply.github.com>
Date: Tue, 21 Jan 2025 23:00:53 -0500
Subject: [PATCH 10/17] Delete 0206-reverse-linked-list/README.md
---
0206-reverse-linked-list/README.md | 34 ------------------------------
1 file changed, 34 deletions(-)
delete mode 100644 0206-reverse-linked-list/README.md
diff --git a/0206-reverse-linked-list/README.md b/0206-reverse-linked-list/README.md
deleted file mode 100644
index d0e5a2292..000000000
--- a/0206-reverse-linked-list/README.md
+++ /dev/null
@@ -1,34 +0,0 @@
-Easy
Given the head
of a singly linked list, reverse the list, and return the reversed list.
-
-
-Example 1:
-
-
-Input: head = [1,2,3,4,5]
-Output: [5,4,3,2,1]
-
-
-Example 2:
-
-
-Input: head = [1,2]
-Output: [2,1]
-
-
-Example 3:
-
-
-Input: head = []
-Output: []
-
-
-
-Constraints:
-
-
- - The number of nodes in the list is the range
[0, 5000]
.
- -5000 <= Node.val <= 5000
-
-
-
-Follow up: A linked list can be reversed either iteratively or recursively. Could you implement both?
From e6dbc47d37dda979e3aad4834cd16dbb289f3e4f Mon Sep 17 00:00:00 2001
From: Jay Mo <115325888+Jay-Mo-99@users.noreply.github.com>
Date: Tue, 21 Jan 2025 23:01:53 -0500
Subject: [PATCH 11/17] Delete
0206-reverse-linked-list/0206-reverse-linked-list.py
---
.../0206-reverse-linked-list.py | 26 -------------------
1 file changed, 26 deletions(-)
delete mode 100644 0206-reverse-linked-list/0206-reverse-linked-list.py
diff --git a/0206-reverse-linked-list/0206-reverse-linked-list.py b/0206-reverse-linked-list/0206-reverse-linked-list.py
deleted file mode 100644
index b48bb838b..000000000
--- a/0206-reverse-linked-list/0206-reverse-linked-list.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Definition for singly-linked list.
-# class ListNode(object):
-# def __init__(self, val=0, next=None):
-# self.val = val
-# self.next = next
-class Solution(object):
- def reverseList(self, head):
- """
- :type head: Optional[ListNode]
- :rtype: Optional[ListNode]
- """
- temp =[]
- while head:
- temp.append(head.val)
- head = head.next
-
- temp = temp[::-1] #Reverse the temp list
-
- myNode = ListNode() #Create the Listnode instance
- current = myNode
-
- for value in temp:
- current.next = ListNode(value)
- current = current.next
-
- return myNode.next
From f501a9dd22eda9ea861415202ee5276b6f720a3d Mon Sep 17 00:00:00 2001
From: Jay Mo <115325888+Jay-Mo-99@users.noreply.github.com>
Date: Tue, 21 Jan 2025 23:02:06 -0500
Subject: [PATCH 12/17] Delete
0211-design-add-and-search-words-data-structure/0211-design-add-and-search-words-data-structure.py
---
...ign-add-and-search-words-data-structure.py | 34 -------------------
1 file changed, 34 deletions(-)
delete mode 100644 0211-design-add-and-search-words-data-structure/0211-design-add-and-search-words-data-structure.py
diff --git a/0211-design-add-and-search-words-data-structure/0211-design-add-and-search-words-data-structure.py b/0211-design-add-and-search-words-data-structure/0211-design-add-and-search-words-data-structure.py
deleted file mode 100644
index 158dba2ba..000000000
--- a/0211-design-add-and-search-words-data-structure/0211-design-add-and-search-words-data-structure.py
+++ /dev/null
@@ -1,34 +0,0 @@
-class TrieNode:
- def __init__(self):
- self.children = {}
- self.is_end_of_word = False
-
-class WordDictionary:
- def __init__(self):
- self.root = TrieNode()
-
- def addWord(self, word: str) -> None:
- node = self.root
- for char in word:
- if char not in node.children:
- node.children[char] = TrieNode()
- node = node.children[char]
- node.is_end_of_word = True
-
- def search(self, word: str) -> bool:
- def dfs(index, node):
- if index == len(word):
- return node.is_end_of_word
-
- char = word[index]
- if char == '.':
- for child in node.children.values():
- if dfs(index + 1, child):
- return True
- return False
- else:
- if char not in node.children:
- return False
- return dfs(index + 1, node.children[char])
-
- return dfs(0, self.root)
From 18fee1f8b5686434181c4b769c61e4f4fee7be5d Mon Sep 17 00:00:00 2001
From: Jay Mo <115325888+Jay-Mo-99@users.noreply.github.com>
Date: Tue, 21 Jan 2025 23:02:36 -0500
Subject: [PATCH 13/17] Delete
design-add-and-search-words-data-structure/Jay-Mo-99.py
---
.../Jay-Mo-99.py | 129 ------------------
1 file changed, 129 deletions(-)
delete mode 100644 design-add-and-search-words-data-structure/Jay-Mo-99.py
diff --git a/design-add-and-search-words-data-structure/Jay-Mo-99.py b/design-add-and-search-words-data-structure/Jay-Mo-99.py
deleted file mode 100644
index d31c372c5..000000000
--- a/design-add-and-search-words-data-structure/Jay-Mo-99.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# 해석
-
-# 0. TrieNode 클래스 정의:
-# - 각 TrieNode 인스턴스는 다음의 두 가지 속성을 가진다:
-# 1) children: 현재 노드의 자식 노드들을 저장하는 딕셔너리 (문자 -> TrieNode 인스턴스).
-# 2) is_end_of_word: 현재 노드가 단어의 끝인지 나타내는 Boolean 값.
-
-# 1. WordDictionary 클래스 정의:
-# - WordDictionary 클래스는 Trie 자료구조를 사용하여 단어를 저장(addWord)하고 탐색(search)한다.
-
-# 1-1. __init__ 함수:
-# - root는 TrieNode 클래스로 생성된 인스턴스를 가진다.
-# - Trie 자료구조의 시작점(루트 노드) 역할을 한다.
-
-# 1-2. addWord 함수:
-# 1) 루트 노드(self.root)에서 시작.
-# 2) 단어의 각 문자를 순회하며:
-# - 현재 노드의 children에 문자가 없으면, 새 TrieNode를 생성해 추가.
-# - 현재 노드를 해당 문자의 자식 노드로 이동.
-# 3) 단어의 마지막 문자를 처리한 후, 해당 노드의 is_end_of_word를 True로 설정.
-
-
-# 1-3. search 함수:
-# - 주어진 단어가 Trie에 존재하는지 확인하는 함수.
-# - 와일드카드 문자(.)를 처리할 수 있다.
-# - 내부적으로 dfs(깊이 우선 탐색) 함수를 사용하여 트라이를 탐색.
-# - dfs(index, node):
-# 1) 종료 조건: index가 단어 길이에 도달하면, 현재 노드의 is_end_of_word 반환.
-# 2) 현재 문자가 '.'인 경우:
-# - 현재 노드의 모든 자식 노드에 대해 dfs를 호출.
-# - 하나라도 True를 반환하면 True 반환.
-# 3) 현재 문자가 일반 문자인 경우:
-# - 자식 노드에 문자가 없으면 False 반환.
-# - 자식 노드로 이동해 dfs를 재귀 호출.
-
-
-
- #Big O
- # - N: 저장된 모든 단어의 총 문자 수 (Trie에 저장된 모든 문자의 개수).
- # - C: 알파벳의 개수 (영어 기준 최대 26).
-
- #Time Complexity: O(N)
- #- addWord함수 : N에 기반하여 단어 추가
- #- searchWord 함수:
- # - 일반 탐색: O(n), n은 단어의 길이.
- # - 와일드카드 탐색: 최악의 경우 O(C^N),
- # - C는 알파벳 개수 (최대 26).
- # - N은 단어의 길이. 와일드카드 문자가 많을수록 모든 경로를 탐색해야 할 수도 있음.
-
- # - Space Complexity: O(N × C)
- #
- # - 각 노드는:
- # 1) children 딕셔너리를 통해 자식 노드를 저장 (메모리 사용).
- # 2) is_end_of_word 변수 (Boolean 값, O(1)).
- # - Trie에 저장된 단어의 문자 수가 많을수록 메모리 사용량 증가.
-
-class TrieNode:
- def __init__(self):
- self.children = {} #알파벳 a부터 z까지를 자식으로 가짐, 크기 26의 배열이나 딕셔너리를 사용.
- self.is_end_of_word = False #어떤 단어의 끝인지 나타내는 Boolean 값
- #예를 들어, "note"이라는 단어의 'e'에 해당하는 노드의 is_end_of_word가 True, 'n'
-
-class WordDictionary:
- def __init__(self):
- self.root = TrieNode() # WD로 생성된 인스턴스.root = TrieNode 인스턴스
-
- def addWord(self, word: str) -> None:
- node = self.root #node에 self.root를 부여
- for char in word: # 매개변수 word를 하나씩 순회하며 char에 저장 (예: word="note" -> char="n", "o", "t", "e")
- if char not in node.children: # 만약 char가 현재 노드의 자식 노드 목록에 없다면
- node.children[char] = TrieNode()
- #node.children[char]을 TrideNode 인스턴스로 생성
- # self.root.children = {
- # "n": TrieNode() # "n" 키가 추가되고, 값으로 새로운 TrieNode 인스턴스가 들어감
- # }
-
- #Example1:
- #root
- #└── "n" (children={}, is_end_of_word=False)
-
- #Example2:
- #└── "n" (children={}, is_end_of_word=False)
- # └── "o" (children={}, is_end_of_word=False)
- node = node.children[char] #node를 현 node의 children[char]로 이동
- #Example1:
- # node = node.children["n"]
-
- #Example2:
- # node = node.children["o"]
- node.is_end_of_word = True
- #After for loop, 끝 노드의 is_end_of_word를 True로 전환
-
- #Example 4:
- #root
- #└── "n"
- #└── "o"
- #└── "t"
- #└── "e" (children={}, is_end_of_word=True)
-
- def search(self, word: str) -> bool:
- def dfs(index, node): # DFS 함수 정의
- # 1) 종료 조건: 모든 문자를 탐색한 경우
- if index == len(word):
- return node.is_end_of_word # 단어 끝 여부 반환
- # 2) 현재 문자 처리
- char = word[index]
- if char == '.': # 2-1) 와일드카드인 경우
- for child in node.children.values(): # 모든 자식 노드 탐색
- if dfs(index + 1, child): #dfs를 재귀호출 하여 다음 노드로 탐색 재개
- return True #재귀 이후에 있으면 True
- return False #없으면 False
- else: # 2-2) 일반 문자 처리
- if char not in node.children: # 현재 문자가 자식 노드에 없는 경우 False
- return False
- return dfs(index + 1, node.children[char]) # 다음 노드로 이동하여 탐색
-
- return dfs(0, self.root)
- #1. def dfs를 self.root 위치에서 첫 호출.
-
-
-
-
-
-
-
-
-
-
-
From 222b461311752e2315fdb31832ee14a45ab43fec Mon Sep 17 00:00:00 2001
From: unknown
Date: Wed, 22 Jan 2025 18:25:12 -0500
Subject: [PATCH 14/17] Solve: Longest Substring Without Repeating Characters
---
.../Jay-Mo-99.py | 36 +++++++++++++++++++
1 file changed, 36 insertions(+)
create mode 100644 longest-substring-without-repeating-characters/Jay-Mo-99.py
diff --git a/longest-substring-without-repeating-characters/Jay-Mo-99.py b/longest-substring-without-repeating-characters/Jay-Mo-99.py
new file mode 100644
index 000000000..3ddf70e67
--- /dev/null
+++ b/longest-substring-without-repeating-characters/Jay-Mo-99.py
@@ -0,0 +1,36 @@
+ #해석
+ #
+
+
+ #Big O
+ #- N: str s의 길이
+
+ #Time Complexity: O(N)
+ #- start,end: 각각 최대 N번 움직임 -> O(N)
+ #- set의 삽입, 삭제 -> O(1)
+
+ #Space Complexity: O(N)
+ #- chars: 최악의 경우 chars는 s의 모든 char을 저장한다 -> O(N)
+
+class Solution:
+ def lengthOfLongestSubstring(self, s: str) -> int:
+ max_len = 0
+ chars = set() #현 윈도우 내 중복 없이 존재하는 문자들을 저장하는 set
+ start, end = 0, 0 # 슬라이딩 윈도우의 start 인덱스, end 인덱스
+ #end가 s의 마지막 인덱스에 도달할때까지 반복
+ while end < len(s):
+ #s[end]가 chars에 존재하면
+ if s[end] in chars:
+ #chars의 s[start]를 제거
+ chars.remove(s[start])
+ #start를 오른쪽으로 이동, 윈도우 축소
+ start += 1
+ else: #s[end] 가 chars에 존재하지 않으면
+ chars.add(s[end]) #해당 s[end]를 chars에 추가해준다
+ end += 1 #end를 오른쪽으로 옮겨 윈도우 확장
+ max_len = max(end - start, max_len) #start-end 계산하여 update
+ return max_len
+
+mySolution = Solution()
+mySolution.lengthOfLongestSubstring("pwwkew")
+
From 80b661aa86b0766eb87d971d73d53d8159108fcb Mon Sep 17 00:00:00 2001
From: unknown
Date: Wed, 22 Jan 2025 23:18:02 -0500
Subject: [PATCH 15/17] Solve: number of islands
---
number-of-islands/Jay-Mo-99.py | 60 ++++++++++++++++++++++++++++++++++
1 file changed, 60 insertions(+)
create mode 100644 number-of-islands/Jay-Mo-99.py
diff --git a/number-of-islands/Jay-Mo-99.py b/number-of-islands/Jay-Mo-99.py
new file mode 100644
index 000000000..c04b294b1
--- /dev/null
+++ b/number-of-islands/Jay-Mo-99.py
@@ -0,0 +1,60 @@
+ #해석
+ # r,c nested loop로 grid의 모든 element를 검사한다
+ # 만약 1인 element를 만나면 sink함수를 호출한다
+ # -sink 함수는 해당 element를 0으로 만들고 해당 element의 좌,우,상,하가 1인지 체크한다
+ # -만약 1이 있다면 또 sink를 반복 호출하며 위의 검사를 반복한다.(1이 없을때까지)
+ # -만약 더이상 연결된 1이 없다면 재귀 호출 종료.
+ # sink함수 종료 시시 nested loop로 돌아와서 이후후 1인 element를 찾는다.
+ # grid의 1이 sink로 모두 없어지면 return cls한다.
+
+
+ #Big O
+ #- M: grid의 행의 갯수(r)
+ #- N: grid의 열의 갯수(c)
+
+ #Time Complexity: O(M*N)
+ #- for loop: 이중 루프로 grid의 모든 element에 도달 -> O(M*N)
+ #- sink(row,col): 최악의 경우 sink함수는 M*N번 호출 -> O(M*N)
+
+ #Space Complexity: O(M∗N)
+ #- sink 재귀호출:
+ # 최악의 경우 sink함수는 스택에 M*N번 재귀 호출 당한다.
+ # 스택에 해당 메모리 누적(재귀 호출 스택의 깊이가 M*N) -> O(M*N)
+from typing import List
+class Solution:
+ def numIslands(self, grid: List[List[str]]) -> int:
+ def sink(row, col):
+ grid[row][col] = "0"
+
+ for r, c in [
+ (row, col - 1), #Left
+ (row, col + 1), #Right
+ (row - 1, col), #Up
+ (row + 1, col), #Down
+ ]:
+ # If the neighbor cell is within bounds and is land ("1"), sink it recursively.
+ if 0 <= r < len(grid) and 0 <= c < len(grid[r]):
+ if grid[r][c] == "1":
+ sink(r, c)
+
+ cnt = 0 # Count the number of islands.
+ # Loop through every cell in the grid.
+ for r in range(len(grid)):
+ for c in range(len(grid[r])):
+ if grid[r][c] == "1":
+ cnt += 1
+ sink(r, c) ## Sink the entire island by converting all connected "1"s to "0"s.
+ return cnt
+
+mySolution = Solution()
+mySolution.numIslands(
+ [
+ ["1","1","1","1","0"],
+ ["1","1","0","1","0"],
+ ["1","1","0","0","0"],
+ ["0","0","0","0","0"]
+ ]
+)
+
+
+
From f1874c86a49abe3ef869817f92a5d3b8bfec50f5 Mon Sep 17 00:00:00 2001
From: unknown
Date: Fri, 24 Jan 2025 17:54:08 -0500
Subject: [PATCH 16/17] Solve: unique-paths
---
unique-paths/Jay-Mo-99.py | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
create mode 100644 unique-paths/Jay-Mo-99.py
diff --git a/unique-paths/Jay-Mo-99.py b/unique-paths/Jay-Mo-99.py
new file mode 100644
index 000000000..0d27adec2
--- /dev/null
+++ b/unique-paths/Jay-Mo-99.py
@@ -0,0 +1,37 @@
+ # 해석
+ # grid는 행렬(matrix)처럼 격자의 형태이다.
+ # 행이 m개라는 뜻은 좌표 상 (0,0), (1,0), ..., (m-1,0)까지 존재한다는 뜻이다.
+ # 열이 n개라는 뜻은 좌표 상 (0,0), (0,1), ..., (0,n-1)까지 존재한다는 뜻이다.
+ # 따라서 (0,0)에서 (m-1,n-1)까지의 모든 가능한 경로 수를 구해야 한다.
+ # - 아래로 m-1번 이동하고, 오른쪽으로 n-1번 이동해야 한다.
+ # - 총 이동 횟수는 m-1 + n-1 = m+n-2이다.
+ # - 총 이동 횟수 내부에서 아래로 m-1번 오른쪽으로 (n-1)번의 조합의 경우의 수를 구한다.
+ # - 예를 들어, 아래로 3번 오른쪽으로 다섯번으로 만들수 있는 모든 경우의 수를 구한다 ^^^>>>>> : ^와 > 가능한 조합을 찾아준다.
+ # 공식: (m+n-2)! / (m-1)! / (n-1)!
+
+
+ #Big O
+ #- N: int m의 크기
+ #- K: int n의 크기
+
+ #Time Complexity: O(M+K)
+ #- for i in range(1,m+1-1): m과 n의 크기의 합에 영향받아 계산 진행 -> O(N+K)
+
+ #Space Complexity: O(1)
+ #- up,down1,down2 - 변수와 변수를 업데이트하는 사칙연산은 상수로 여겨져 O(1),
+class Solution:
+ def uniquePaths(self, m: int, n: int) -> int:
+ up = 1 #분자
+ down1 = 1 #분모 1
+ down2=1 #분모 2
+
+
+ for i in range(1,m+n-1):
+ up *= i
+ for i in range(1,m):
+ down1 *= i
+ for i in range(1,n):
+ down2 *= i
+
+ return int(up/(down1*down2))
+
From a8812180165a91febc74f4287863f0981eb8f371 Mon Sep 17 00:00:00 2001
From: unknown
Date: Fri, 24 Jan 2025 18:37:48 -0500
Subject: [PATCH 17/17] Solve: set-matrix-zeroes
---
set-matrix-zeroes/Jay-Mo-99.py | 45 ++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
create mode 100644 set-matrix-zeroes/Jay-Mo-99.py
diff --git a/set-matrix-zeroes/Jay-Mo-99.py b/set-matrix-zeroes/Jay-Mo-99.py
new file mode 100644
index 000000000..ff4f722dd
--- /dev/null
+++ b/set-matrix-zeroes/Jay-Mo-99.py
@@ -0,0 +1,45 @@
+ #해석
+ # matrix의 모든 element를 검사한다, 만약 0을 발견하면 해당 element와 같은 row와 col을 가진 element를 "a" 로 바꾼다.
+ # 두번째로 matrix의 모든 element를 검사한다, 만약 a를 발견하면 이를 0으로 바꾼다.
+
+
+ #Big O
+ #- N: row의 크기(matrix 행의 갯수)
+ #- K: col의 크기(matrix 열의 갯수 )
+
+ #Time Complexity: O(N*K*(N+K))
+ #- for nested loop : 행의 갯수(N) 당 열의 갯수만큼(K) 루프 작동 -> O(N*K)
+ # - 최악의 경우, 첫번째 루프에서 for i in range(rows)가 M번 발동, for j in range(cols)가 N번 발동 -> O(N+K)
+
+ #Space Complexity: O(1)
+ #- rows, cols: 변수의 할당과 업데이트는 상수 취급한다 -> O(1)
+from typing import List
+
+
+class Solution:
+ def setZeroes(self, matrix: List[List[int]]) -> None:
+ """
+ Do not return anything, modify matrix in-place instead.
+ """
+ rows, cols = len(matrix), len(matrix[0]) #rows와 cols에 matrix의 좌표 부여
+
+ # 1차 matrix 순회: 0을 발견하면, 그 element의 같은 행과 열의 0이 아닌 수를 임시 값 "a"로 바꾸기
+ for r in range(rows):
+ for c in range(cols):
+ if matrix[r][c] == 0:
+ # 해당 행과 열의 0이 아닌 모든 값을 임시로 "a"로 변경
+ for i in range(rows): # 해당 열의 모든 값
+ if matrix[i][c] != 0:
+ matrix[i][c] = "a"
+ for j in range(cols): # 해당 행의 0이 아닌 모든 값을 "a"로 변경
+ if matrix[r][j] != 0:
+ matrix[r][j] = "a"
+
+ # 2차 matrix순회: "a"를 가진 수를 0으로 바꿔준다.
+ for r in range(rows):
+ for c in range(cols):
+ if matrix[r][c] == "a":
+ matrix[r][c] = 0
+
+
+