-
-
Notifications
You must be signed in to change notification settings - Fork 362
[JeonJe] WEEK 05 Solutions #2767
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| import java.util.*; | ||
|
|
||
| // TC: O(n) | ||
| // SC: O(1) | ||
| class Solution { | ||
| public int maxProfit(int[] prices) { | ||
| int n = prices.length; | ||
| int maxProfit = 0; | ||
| int minPrice = prices[0]; | ||
|
|
||
| for (int sellDay = 1; sellDay < n; sellDay++) { | ||
| minPrice = Math.min(minPrice, prices[sellDay]); | ||
| maxProfit = Math.max(maxProfit, prices[sellDay] - minPrice); | ||
| } | ||
|
Comment on lines
+11
to
+14
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sellDay 변수명 직관적이어서 좋은 거 같네요 |
||
|
|
||
| return maxProfit; | ||
| } | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
풀이 1:
|
| 유저 분석 | 실제 분석 | 결과 | |
|---|---|---|---|
| Time | O(n) | O(total length of all strings) | ❌ |
| Space | O(n) | O(total length of all strings) | ❌ |
피드백: 길이 접두사 방식으로 인코딩하여 구분자를 이용해 디코딩한다.
개선 제안: 현재 구현이 적절해 보입니다.
풀이 2: Solution.decode — Time: O(total length of encoded string) / Space: O(number of strings + total length of strings)
| 복잡도 | |
|---|---|
| Time | O(total length of encoded string) |
| Space | O(number of strings + total length of strings) |
피드백: 인덱스 기반 파싱으로 정확한 복원이 가능하다.
개선 제안: 현재 구현이 적절해 보입니다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| import java.util.*; | ||
|
|
||
| // TC: O(n) | ||
| // SC: O(n) | ||
| class Solution { | ||
|
|
||
| private static final String DELIMITER = ","; | ||
|
|
||
| // ["mydata"] -> "6,mydata" | ||
| public String encode(List<String> strs) { | ||
| StringBuilder sb = new StringBuilder(); | ||
| for (String s : strs) { | ||
| sb.append(s.length()).append(DELIMITER).append(s); | ||
| } | ||
| return sb.toString(); | ||
| } | ||
|
|
||
| // "6,mydata" -> ["mydata"] | ||
| public List<String> decode(String str) { | ||
| List<String> answer = new ArrayList<>(); | ||
|
|
||
| int cursor = 0; | ||
| while (cursor < str.length()) { | ||
| int indexOfDelimiter = str.indexOf(DELIMITER, cursor); | ||
| int dataStart = indexOfDelimiter + 1; | ||
| int dataLength = Integer.parseInt(str.substring(cursor, indexOfDelimiter)); | ||
|
|
||
| answer.add(str.substring(dataStart, dataStart + dataLength)); | ||
| cursor = dataStart + dataLength; | ||
| } | ||
|
|
||
| return answer; | ||
| } | ||
| } |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 정렬된 문자 배열을 해시맵 키로 사용해 애너그램 그룹화를 구현한다. 개선 제안: 현재 구현이 적절해 보입니다. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| import java.util.*; | ||
|
|
||
| // TC: O(n * k log k) | ||
| // SC: O(n * k) | ||
| class Solution { | ||
| public List<List<String>> groupAnagrams(String[] strs) { | ||
| List<List<String>> answer = new ArrayList<>(); | ||
| Map<String, List<String>> map = new HashMap<>(); | ||
|
|
||
| for (String str : strs) { | ||
| char[] charArray = str.toCharArray(); | ||
| Arrays.sort(charArray); | ||
| String sortedStr = String.valueOf(charArray); | ||
|
|
||
| map.computeIfAbsent(sortedStr, k -> new ArrayList<>()).add(str); | ||
| } | ||
|
|
||
| for (String s : map.keySet()) { | ||
| answer.add(map.get(s)); | ||
| } | ||
|
|
||
| return answer; | ||
| } | ||
| } |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 배열 기반 자식 노드와 끝 여부 표시로 빠른 검색을 제공한다. 개선 제안: 현재 구현이 적절해 보입니다.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| // TC: O(L) | ||
| // SC: O(N * L) | ||
| class TrieNode { | ||
|
|
||
| public boolean isEnd; | ||
| public TrieNode[] children = new TrieNode[26]; | ||
| } | ||
|
|
||
| class Trie { | ||
|
|
||
| private final TrieNode root; | ||
|
|
||
| public Trie() { | ||
| root = new TrieNode(); | ||
| } | ||
|
|
||
| public void insert(String word) { | ||
| TrieNode node = root; | ||
| for (char c : word.toCharArray()) { | ||
| if (node.children[c - 'a'] == null) { | ||
| node.children[c - 'a'] = new TrieNode(); | ||
| } | ||
| node = node.children[c - 'a']; | ||
|
Comment on lines
+20
to
+23
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. children[c - 'a'] 는 TrieNode의 세부 구현에 가까운데 Trie에 c - 'a'가 여러 코드에 걸쳐 나타나고 있는 것 같습니다. TrieNode에서 node.getChildren(c) 와 같은 방식으로 제공하는 건 어떨까요?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 미처 생각 못했던 부분인데, 함수로 감싸면 가독성도 높히고 실수도 줄일 수 있을 것 같네요. |
||
| } | ||
| node.isEnd = true; | ||
| } | ||
|
|
||
| public boolean search(String word) { | ||
| TrieNode node = traverse(word); | ||
| return node != null && node.isEnd; | ||
| } | ||
|
|
||
| public boolean startsWith(String prefix) { | ||
| return traverse(prefix) != null; | ||
| } | ||
|
|
||
| private TrieNode traverse(String sequence) { | ||
| TrieNode node = root; | ||
| for (char c : sequence.toCharArray()) { | ||
| if (node.children[c - 'a'] == null) { | ||
| return null; | ||
| } | ||
| node = node.children[c - 'a']; | ||
| } | ||
| return node; | ||
| } | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 뒤에서 앞으로 dp를 채우는 전형적 풀이로 충분하다. 개선 제안: 현재 구현이 적절해 보입니다. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| import java.util.*; | ||
|
|
||
| // n = s.length(), m = wordDict.size(), L = 사전 단어의 최대 길이 | ||
| // TC: O(n * m * L) | ||
| // SC: O(n) | ||
| class Solution { | ||
| public boolean wordBreak(String s, List<String> wordDict) { | ||
| int n = s.length(); | ||
|
|
||
| // dp[i] = 인덱스 i부터 시작하는 뒷부분을 사전 단어로 빈틈없이 쪼갤 수 있는가 | ||
| boolean[] dp = new boolean[n + 1]; | ||
| dp[n] = true; | ||
|
|
||
| // dp[i]는 자기보다 오른쪽의 dp[i + word.length()]를 참조하므로 뒤에서 앞으로 채운다 | ||
| for (int i = n - 1; i >= 0; i--) { | ||
| for (String word : wordDict) { | ||
| // startsWith(word, i)는 substring 없이 i번째부터 비교한다 | ||
| if (s.startsWith(word, i) && dp[i + word.length()]) { | ||
| dp[i] = true; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return dp[0]; | ||
| } | ||
|
Comment on lines
+15
to
+26
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 앞에서부터 누적해서 푸는 분들이 많았는데 반대로 푸셔서 흥미로웠습니다. 앞에서부터 푸는 것도 고려하셨을 거 같은데 뒤에서부터 푸신 이유가 있으실까요?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 재귀 형식의 탑다운 방식으로 먼저 풀다보니, 바텀업 방식도 자연스럽게 뒤에서 앞 방향으로 생각하게 되었습니다. |
||
| } | ||
|
|
||
| // 첫 번째 풀이 — top-down 재귀 + 메모이제이션 (TC: O(n^2 * m), SC: O(n^2)) | ||
| // 남은 뒷부분을 문자열 그대로 메모 key로 써서 substring으로 새 문자열을 만들고 그 문자열을 n개까지 저장한다. | ||
| // | ||
| // public boolean wordBreak(String s, List<String> wordDict) { | ||
| // return dfs(s, wordDict, new HashMap<>()); | ||
| // } | ||
| // | ||
| // private boolean dfs(String s, List<String> wordDict, Map<String, Boolean> memo) { | ||
| // if (s.isEmpty()) return true; | ||
| // if (memo.containsKey(s)) return memo.get(s); | ||
| // | ||
| // for (String word : wordDict) { | ||
| // if (s.startsWith(word)) { | ||
| // if (dfs(s.substring(word.length()), wordDict, memo)) { | ||
| // memo.put(s, true); | ||
| // return true; | ||
| // } | ||
| // } | ||
| // } | ||
| // | ||
| // memo.put(s, false); | ||
| // return false; | ||
| // } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 최소 가격을 추적하고 각 날의 이익을 비교해 최댓값을 구하는 표준 풀이이다.
개선 제안: 현재 구현이 적절해 보입니다.