Skip to content

[Yn3-3xh] WEEK 05 Solutions #1402

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

Merged
merged 5 commits into from
May 3, 2025
Merged
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
19 changes: 19 additions & 0 deletions best-time-to-buy-and-sell-stock/Yn3-3xh.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
[문제풀이]
- 작은수를 두고, 큰수에 뺀 값을 구하자.
time: O(N), space: O(1)

[회고]
이번 문제는 난이도가 easy인 덕분에 무리없이 풀었던 것 같다.
*/
class Solution {
public int maxProfit(int[] prices) {
int min = prices[0];
int max = 0;
for (int i = 1; i < prices.length; i++) {
min = Math.min(min, prices[i]);
max = Math.max(max, prices[i] - min);
}
return max;
}
}
83 changes: 83 additions & 0 deletions group-anagrams/Yn3-3xh.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/**
[문제풀이]
- 이전에 배열로 풀었던 아나그램 솔루션을 참고해보자.
time: O(N^2 * M), space: O(N * M)
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
List<List<String>> result = new ArrayList<>();
boolean[] used = new boolean[strs.length];

for (int i = 0; i < strs.length; i++) {
if (used[i]) {
continue;
}

List<String> sub = new ArrayList<>();
String current = strs[i];
sub.add(current);
used[i] = true;

for (int j = i + 1; j < strs.length; j++) {
String next = strs[j];
if (isAnagram(current, next)) {
sub.add(next);
used[j] = true;
}
}
result.add(sub);
}
return result;
}

private boolean isAnagram(String current, String next) {
if (current.length() != next.length()) {
return false;
}

int[] counting = new int[26];
for (char ch : current.toCharArray()) {
counting[ch - 'a']++;
}
for (char ch : next.toCharArray()) {
counting[ch - 'a']--;
}

for (int count : counting) {
if (count != 0) {
return false;
}
}
return true;
}
}

- sorting
time: O(N * M log M), space: O(N * M)

[회고]
중첩 for문을 써서 시간복잡도 커트라인에 턱걸이했다..

이전에 풀었던 아나그램을 베이스로 풀다 보니 최적화하기가 어려운 것 같다.
문제에 맞는 풀이법을 생각해보자..

주어진 문자열을 문자 배열로 만들고, 문자 배열을 sorting한다면 아나그램의 key가 된다.
key가 없으면 list를 만들어주고, 있으면 그 key에 문자열을 넣어주자.
해설을 보고, 이해하고 풀고나면 쉬운데..
왜 처음에 못 풀까..
*/
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> result = new HashMap<>();

for (String str : strs) {
char[] tempArray = str.toCharArray();
Arrays.sort(tempArray);
String key = new String(tempArray);

result.putIfAbsent(key, new ArrayList<>());
result.get(key).add(str);
}
return new ArrayList<>(result.values());
}
}

96 changes: 96 additions & 0 deletions implement-trie-prefix-tree/Yn3-3xh.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/**
[문제풀이]
- Node를 만들자
time: O(N), space: O(N)

[회고]
노드를 만드는 접근은 맞았는데, 그 뒤로 안풀려서 해설을 보니 노드의 길이를 26으로 한다.
이 부분에서 이해하기가 어려웠는데 아래를 보고 이해됐다.
(root)
├── c
│ ├── a
│ │ ├── t (end)
│ │ └── r (end)
└── d
└── o
└── g (end)

주어진 문자열을 핸들링하는 역할은 노드가 가지도록 노드 안에 솔루션을 구현했다.
*/
class Trie {
Node root;

public Trie() {
root = new Node();
}

public void insert(String word) {
root.insert(word);
}

public boolean search(String word) {
return root.search(word);
}

public boolean startsWith(String prefix) {
return root.startsWith(prefix);
}
}

class Node {
Node[] nodes;
boolean isEnd;

Node() {
nodes = new Node[26];
}

void insert(String word) {
Node current = this;
for (char ch : word.toCharArray()) {
int index = ch - 'a';
if (current.nodes[index] == null) {
current.nodes[index] = new Node();
}
current = current.nodes[index];
}
current.isEnd = true;
}

boolean search(String word) {
Node current = this;
for (char ch : word.toCharArray()) {
int index = ch - 'a';
if (current.nodes[index] == null) {
return false;
}
current = current.nodes[index];
}

if (current.isEnd) {
return true;
}
return false;
}

boolean startsWith(String prefix) {
Node current = this;
for (char ch : prefix.toCharArray()) {
int index = ch - 'a';
if (current.nodes[index] == null) {
return false;
}
current = current.nodes[index];
}
return true;
}
}

/**
* Your Trie object will be instantiated and called as such:
* Trie obj = new Trie();
* obj.insert(word);
* boolean param_2 = obj.search(word);
* boolean param_3 = obj.startsWith(prefix);
*/

55 changes: 55 additions & 0 deletions word-break/Yn3-3xh.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
[문제풀이]
- startsWith으로 있으면 substring하면서 반복해보자.
- 주어진 list를 map으로 활용
- failed
s = "cars"
wordDict = ["car","ca","rs"]
---
class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
for (String word: wordDict) {
s = s.replace(word, "");
}

if (s.length() == 0) {
return true;
}
return false;
}
}

- DP
time: O(N^2), space: O(N)

[회고]
처음엔 너무 쉽게 생각해서 안될 것 같긴했다..
DP로 풀면 될 것 같은데..
해설을 보면 이해가 되지만, 항상 DP 접근이 잘 안된다..
*/
class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
// "applepenapple", ["apple","pen"]
int sLen = s.length();
boolean[] dp = new boolean[sLen + 1];
dp[0] = true;

int maxLen = 0;
for (String word: wordDict) {
maxLen = Math.max(maxLen, word.length());
} // 5

for (int i = 1; i <= sLen; i++) { // 1 ~ 13
// applepenapple > apple > 5
for (int j = i - 1; j >= 0; j--) {
// applepenapple > apple > index:4 > 0
if (dp[j] && wordDict.contains(s.substring(j, i))) {
dp[i] = true;
break;
}
}
}
return dp[sLen];
}
}