Skip to content

Commit 3d0fa90

Browse files
authored
Merge pull request #2161 from radiantchoi/main
[radiantchoi] WEEK 05 Solutions
2 parents 841cfc8 + 049010f commit 3d0fa90

File tree

4 files changed

+182
-0
lines changed

4 files changed

+182
-0
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
class Solution:
2+
def maxProfit(self, prices: List[int]) -> int:
3+
# profit: ์ตœ๋Œ€ ์ด์ต
4+
profit = 0
5+
6+
# current_minimum: ํ˜„์žฌ๊นŒ์ง€์˜ ์ตœ์†Œ ๊ฐ€๊ฒฉ
7+
current_minimum = prices[0]
8+
9+
# current_profit: ํ˜„์žฌ๊นŒ์ง€์˜ ์ตœ๋Œ€ ์ด์ต
10+
current_profit = 0
11+
12+
# ์ „์ฒด ๋ฐฐ์—ด์—์„œ ์ตœ์†Ÿ๊ฐ’๊ณผ, ์ตœ์†Ÿ๊ฐ’ ์ธ๋ฑ์Šค ์ดํ›„ ์ตœ๋Œ“๊ฐ’์„ ์ด์ต์œผ๋กœ ๊ณ„์‚ฐํ•˜๋Š” ๋ฐ˜๋ณต๋ฌธ
13+
for i in range(1, len(prices)):
14+
# ์ด์ต์ด ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ ํ˜„์žฌ ์ด์ต ๊ฐฑ์‹ 
15+
# ํ˜„์žฌ ์ด์ต์„ ๊ฐฑ์‹ ํ•  ๋•Œ๋งˆ๋‹ค ์ง€๊ธˆ๊นŒ์ง€์˜ ์ตœ๋Œ€ ์ด์ต๋„ ๊ฐฑ์‹ 
16+
if prices[i] > current_minimum:
17+
current_profit = max(current_profit, prices[i] - current_minimum)
18+
profit = max(profit, current_profit)
19+
# ์ด์ต์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ์ตœ์†Ÿ๊ฐ’ ๊ฐฑ์‹ 
20+
else:
21+
current_minimum = prices[i]
22+
23+
# ์ตœ๋Œ€ ์ด์ต๋งŒ ์ €์žฅ๋˜์–ด ๋ฐ˜ํ™˜
24+
return profit
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
class Solution {
2+
func groupAnagrams(_ strs: [String]) -> [[String]] {
3+
// ์• ๋„ˆ๊ทธ๋žจ์„ ์ €์žฅํ•  ๋”•์…”๋„ˆ๋ฆฌ
4+
var groups = [String: [String]]()
5+
6+
for str in strs {
7+
// ๊ฐ๊ฐ์˜ ๋ฌธ์ž์—ด๋ณ„๋กœ ๋“ฑ์žฅํ•˜๋Š” ๊ธ€์ž์˜ ๊ฐฏ์ˆ˜๋ฅผ ์ €์žฅํ•  ๋”•์…”๋„ˆ๋ฆฌ
8+
var occurences = [Character: Int]()
9+
10+
// ๋“ฑ์žฅํ•˜๋Š” ๊ธ€์ž์˜ ๊ฐฏ์ˆ˜๋ฅผ ๊ณ„์‚ฐ
11+
// Swift์—์„œ๋Š” ๊ธ€์ž๋ฅผ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•ด ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Œ
12+
for letter in Array(str) {
13+
if let val = occurences[letter] {
14+
occurences[letter] = val + 1
15+
} else {
16+
occurences[letter] = 1
17+
}
18+
}
19+
20+
let anagramKey = makeAnagramKey(for: occurences)
21+
22+
// ๋”•์…”๋„ˆ๋ฆฌ์— ์ด๋ฏธ ๊ฐ™์€ ์• ๋„ˆ๊ทธ๋žจ ํ‚ค๊ฐ€ ์กด์žฌํ•  ๊ฒฝ์šฐ, ํ•ด๋‹น ํ‚ค์— ๋Œ€ํ•œ ๊ฐ’์— ํ˜„์žฌ ๋ฌธ์ž์—ด ์ถ”๊ฐ€
23+
if let group = groups[anagramKey] {
24+
groups[anagramKey]!.append(str)
25+
} else {
26+
// ๋”•์…”๋„ˆ๋ฆฌ์— ํ‚ค๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ, ํ‚ค๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ํ˜„์žฌ ๋ฌธ์ž์—ด์„ ๊ฐ’์œผ๋กœ ์ถ”๊ฐ€
27+
groups[anagramKey] = [str]
28+
}
29+
}
30+
31+
// ๋”•์…”๋„ˆ๋ฆฌ์˜ ๊ฐ’๋“ค์„ ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜ - ๋ฐ˜ํ™˜ ์ˆœ์„œ๋Š” ์ƒ๊ด€์—†๋‹ค๊ณ  ๋ฌธ์ œ์— ๋ช…์‹œ
32+
// ๋ฐ˜ํ™˜ ์ˆœ์„œ๊ฐ€ ํ•„์š”ํ•  ๊ฒฝ์šฐ ์• ๋„ˆ๊ทธ๋žจ ํ‚ค์˜ ๋“ฑ์žฅ ์ˆœ์„œ๋ฅผ ์ €์žฅํ•˜๋Š” ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ์ƒˆ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Œ
33+
return Array(groups.values)
34+
}
35+
36+
// ๋“ฑ์žฅํ•˜๋Š” ๊ธ€์ž์˜ ๊ฐฏ์ˆ˜์— ๋”ฐ๋ผ ๋”•์…”๋„ˆ๋ฆฌ์˜ ํ‚ค๋ฅผ ๋งŒ๋“œ๋Š” ํ•จ์ˆ˜
37+
func makeAnagramKey(for occurences: [Character: Int]) -> String {
38+
// ๊ฐ™์€ ์• ๋„ˆ๊ทธ๋žจ์„ ๊ฐ€์งˆ ๋•Œ ๊ฐ™์€ ํ‚ค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด, ์ •๋ ฌ ์ ์šฉ
39+
return occurences.keys.sorted().reduce("") { (previous, key) in
40+
var previous = previous
41+
previous += String(key)
42+
previous += String(occurences[key]!)
43+
44+
return previous
45+
}
46+
}
47+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
class Trie {
2+
private let root: TrieNode
3+
4+
init() {
5+
self.root = TrieNode()
6+
}
7+
8+
func insert(_ word: String) {
9+
var node = root // ๋ฃจํŠธ ๋…ธ๋“œ์˜ ํฌ์ธํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ 
10+
11+
// ๋‹จ์–ด์˜ ๊ฐ ๊ธ€์ž๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ, ์ด๋ฏธ ์žˆ๋‹ค๋ฉด ํ•ด๋‹น ๋…ธ๋“œ๋กœ ์ด๋™ํ•˜๊ณ ,
12+
// ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ์ƒˆ๋กœ์šด ๋…ธ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์—ฐ๊ฒฐ
13+
for letter in word {
14+
if let childNode = node.children[letter] {
15+
node = childNode
16+
} else {
17+
let newNode = TrieNode()
18+
node.children[letter] = newNode
19+
node = newNode
20+
}
21+
}
22+
23+
// ๋‹จ์–ด์˜ ๋งˆ์ง€๋ง‰ ๊ธ€์ž ๋…ธ๋“œ์— isTerminating์„ true๋กœ ์„ค์ •
24+
node.isTerminating = true
25+
}
26+
27+
func search(_ word: String) -> Bool {
28+
var node = root
29+
30+
// ๋…ธ๋“œ ํฌ์ธํ„ฐ๋งŒ ์ œ๊ณตํ•˜์—ฌ ์ˆœํšŒ ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๊ณ ,
31+
// ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ๊ฐ€ isTerminating์ด true์ธ์ง€ ํ™•์ธ
32+
guard traverse(startsWith: &node, quote: word) else { return false }
33+
guard node.isTerminating else { return false }
34+
35+
return true
36+
}
37+
38+
func startsWith(_ prefix: String) -> Bool {
39+
var node = root
40+
// ๋…ธ๋“œ ํฌ์ธํ„ฐ๋งŒ ์ œ๊ณตํ•˜์—ฌ ์ˆœํšŒ ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜
41+
return traverse(startsWith: &node, quote: prefix)
42+
}
43+
44+
// ํŠธ๋ฆฌ ํƒ์ƒ‰ ๋กœ์ง
45+
// ๋…ธ๋“œ ํฌ์ธํ„ฐ๋ฅผ ๋ฐ›์•„์„œ, ์ˆœํšŒ ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ํฌ์ธํ„ฐ๋ฅผ ๊ต์ฒด
46+
private func traverse(startsWith node: inout TrieNode, quote: String) -> Bool {
47+
for letter in quote {
48+
guard let childNode = node.children[letter] else {
49+
return false
50+
}
51+
52+
node = childNode
53+
}
54+
55+
return true
56+
}
57+
}
58+
59+
// ํŠธ๋ผ์ด์˜ ๊ฐ๊ฐ์˜ ๋…ธ๋“œ ๊ตฌํ˜„
60+
// ์ž์‹ ๋…ธ๋“œ ๋”•์…”๋„ˆ๋ฆฌ์™€, ์ด ๊ธ€์ž๋กœ ๋๋‚˜๋Š” ๋‹จ์–ด๊ฐ€ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ์ €์žฅ
61+
// ๊ธ€์ž ์ž์ฒด๋Š” ๋ถ€๋ชจ ๋…ธ๋“œ ๋”•์…”๋„ˆ๋ฆฌ์˜ ํ‚ค๋กœ ์ €์žฅ๋˜๋ฏ€๋กœ ๋”ฐ๋กœ ์ €์žฅํ•˜์ง€ ์•Š์Œ
62+
// ๋ฃจํŠธ์—๋Š” ์•„๋ฌด ๊ธ€์ž๋„ ๋“ค์–ด๊ฐ€์ง€ ์•Š๋Š”๋‹ค๋Š” Trie์˜ ์กฐ๊ฑด๋„ ์ž๋™์œผ๋กœ ๋งŒ์กฑ
63+
class TrieNode {
64+
var children: [Character: TrieNode]
65+
var isTerminating: Bool
66+
67+
init(children: [Character: TrieNode] = [:], isTerminating: Bool = false) {
68+
self.children = children
69+
self.isTerminating = isTerminating
70+
}
71+
}
72+
73+
/**
74+
* Your Trie object will be instantiated and called as such:
75+
* let obj = Trie()
76+
* obj.insert(word)
77+
* let ret_2: Bool = obj.search(word)
78+
* let ret_3: Bool = obj.startsWith(prefix)
79+
*/

โ€Žword-break/radiantchoi.pyโ€Ž

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
class Solution:
2+
def traverse(self, s: str, wordDict: List[str], checked: int, memo: Dict[int,bool]) -> bool:
3+
# checked์˜ ์˜๋ฏธ: ํ˜„์žฌ๊นŒ์ง€ ์ฒดํฌํ•œ ๋ฌธ์ž์—ด์˜ ๊ธธ์ด - ์•„์ง ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ ๋๊นŒ์ง€ ๊ฐˆ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์žฅ๋‹ดํ•  ์ˆ˜ ์—†์Œ
4+
# ์‹œ์ž‘ ์ธ๋ฑ์Šค๊ฐ€ ๋ฌธ์ž์—ด์˜ ๊ธธ์ด์™€ ๊ฐ™์€ ๊ฒฝ์šฐ, ์ด ๋ฌธ์ž์—ด์— ๋Œ€ํ•ด ๊ฒ€์‚ฌ๋ฅผ ๋งˆ์ณค๋‹ค๋Š” ๋œป (๋‚จ์€ ๊ธธ์ด๊ฐ€ 0)
5+
if checked == len(s):
6+
return True
7+
8+
# ์ง€๊ธˆ ๋‹ค๋ฃจ๋ ค๋Š” ์ธ๋ฑ์Šค๋ฅผ ์ด๋ฏธ ์ฒดํฌํ–ˆ๋‹ค๋ฉด, ํ›„์† ๊ณ„์‚ฐ์„ ํ•˜์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ๋ฐ˜ํ™˜
9+
if checked in memo:
10+
return memo[checked]
11+
12+
for word in wordDict:
13+
# ์Šฌ๋ผ์ด์‹ฑ ๋Œ€์‹  startswith๋ฅผ ์“ฐ๋Š” ๊ฒƒ์ด ์„ฑ๋Šฅ์ƒ ์ด์ ์ด ์žˆ๋‹ค
14+
# ์ง€๊ธˆ ๋ณด๋ ค๋Š” ๋‹จ์–ด๊ฐ€ ๋ฌธ์ž์—ด์˜ prefix์ธ ๊ฒฝ์šฐ, ์ฆ‰ ๋‹ค์Œ ํƒ์ƒ‰์„ ์ˆ˜ํ–‰ํ•ด ๋ณผ ์—ฌ๊ฑด์ด ๋˜๋Š” ๊ฒฝ์šฐ
15+
# ์—ฌ๊ธฐ์„œ ์‹œ์ž‘ํ•ด์„œ ๋๊นŒ์ง€ ๊ฐ”์„ ๋•Œ ๋ฌธ์žฅ์ด ์™„์„ฑ์ด ๋˜๋‹ˆ? ๋ผ๋Š” ๊ฒƒ
16+
17+
# ๋งŒ์•ฝ ๊ฐ€๋Šฅํ•  ๊ฒฝ์šฐ, ๊ฑฐ์ณ์˜จ ๋ชจ๋“  path์— ๋Œ€ํ•ด memo ๋”•์…”๋„ˆ๋ฆฌ์—๋Š” True๊ฐ€ ์ €์žฅ๋˜๊ฒŒ ๋œ๋‹ค.
18+
# ๋˜ํ•œ early return์„ ํ†ตํ•ด ํ›„์† ์ผ€์ด์Šค๋ฅผ ๊ณ„์‚ฐํ•˜์ง€ ์•Š๋Š”๋‹ค.
19+
if s.startswith(word, checked):
20+
if self.traverse(s, wordDict, checked + len(word), memo):
21+
memo[checked] = True
22+
return True
23+
24+
# ์œ„์˜ for๋ฌธ์—์„œ ๋งŒ์กฑํ•˜๋Š” ๊ฒŒ ์—†๋‹ค๋ฉด, ์—ฌ๊ธฐ์„œ ์‹œ์ž‘ํ•ด๊ฐ€์ง€๊ณ ์„œ๋Š” ๋๊นŒ์ง€ ๊ฐˆ ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ
25+
memo[checked] = False
26+
return False
27+
28+
29+
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
30+
memo = {}
31+
32+
return self.traverse(s, wordDict, 0, memo)

0 commit comments

Comments
ย (0)