Skip to content

[forest000014] Week 05 #851

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
Jan 10, 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
30 changes: 30 additions & 0 deletions best-time-to-buy-and-sell-stock/forest000014.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
Time complexity: O(n)
Space complexity: O(1)

i <= j 인 두 인덱스 i, j에 대해서, prices[j] - prices[i]를 최대화해야 한다.

1. i = 0부터 시작하여, 오른쪽으로 순회한다.
2. 현재 값이 max보다 크다면, max를 갱신하고, min과의 차이를 계산한다.
3. 현재 값이 min보다 작다면, min을 갱신하고, max 역시 같은 값으로 갱신한다. (과거로 돌아가서 팔 수는 없으므로)
*/
class Solution {
public int maxProfit(int[] prices) {
int min = 999999;
int max = 0;
int ans = 0;
for (int i = 0; i < prices.length; i++) {
if (prices[i] > max) {
max = prices[i];
if (max - min > ans) {
ans = max - min;
}
}
if (prices[i] < min) {
min = max = prices[i];
}
Comment on lines +17 to +25
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

max라는 변수가 없었으면 알고리즘이 더 간단할 수 있었겠다는 생각이 들었습니다.

Suggested change
if (prices[i] > max) {
max = prices[i];
if (max - min > ans) {
ans = max - min;
}
}
if (prices[i] < min) {
min = max = prices[i];
}
if (prices[i] - min > ans) {
ans = prices[i] - min;
}
if (prices[i] < min) {
min = prices[i];
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

다시 보니 굳이 불필요하게 max라는 변수를 쓸 필요가 없었네요... sweat_smile:
한번 사고의 흐름이 한 방향으로 생기고 나니, 코드를 간결하게 하려고 다시 봐도 잘 안 보이는 것 같네요 ㅠㅠ

}

return ans;
}
}
32 changes: 32 additions & 0 deletions encode-and-decode-strings/forest000014.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
Time Complexity: O(n)
Space Complexity: O(1)

non-ASCII 유니코드 문자를 사용함

To-Do : escaping 방법 학습하기
*/
public class Codec {

// Encodes a list of strings to a single string.
public String encode(List<String> strs) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < strs.size(); i++) {
if (i > 0) {
sb.append('\u2764');
}
sb.append(strs.get(i));
}

return sb.toString();
}

// Decodes a single string to a list of strings.
public List<String> decode(String s) {
return new ArrayList<>(Arrays.asList(s.split("\u2764")));
}
}

// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.decode(codec.encode(strs));
39 changes: 39 additions & 0 deletions group-anagrams/forest000014.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
Time Complexity: O(n)
Space Complexity: O(n)
*/
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<>();

for (String str : strs) {
int[] cnt = new int[26];
for (int i = 0; i < str.length(); i++) {
cnt[str.charAt(i) - 'a']++;
}
char[] chars = new char[str.length()];
int idx = 0;
for (int i = 0; i < 26; i++) {
while (cnt[i] > 0) {
chars[idx++] = (char)(i + 'a');
cnt[i]--;
}
}
String sorted = new String(chars);
if (!map.containsKey(sorted)) {
map.put(sorted, new ArrayList<>());
}
map.get(sorted).add(str);
}

List<List<String>> ans = new ArrayList<>();
for (String key : map.keySet()) {
ans.add(new ArrayList<>());
for (String str : map.get(key)) {
ans.get(ans.size() - 1).add(str);
}
}

return ans;
Comment on lines +29 to +37
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이렇게 사소한 자료 구조 변환은 한 줄로 처리해주시면 위에 더 중요한 코드를 읽는데 더 집중할 수 있을 것 같아요.

Suggested change
List<List<String>> ans = new ArrayList<>();
for (String key : map.keySet()) {
ans.add(new ArrayList<>());
for (String str : map.get(key)) {
ans.get(ans.size() - 1).add(str);
}
}
return ans;
return new ArrayList<>(map.values());

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

앗 이 부분은 map을 단순히 List로 바꾼 것은 아니고, 1-depth로 되어있는 map을 2-depth로 변환하기 위한 코드입니다
다시 보니 달레님께서 말씀해주신 게 그 기능이네요! 이런 식으로 할 수 있다는 걸 새롭게 배웠습니다 😄

}
}
71 changes: 71 additions & 0 deletions implement-trie-prefix-tree/forest000014.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
Time Complexity (n = length of word/prefix)
- initialization: O(1)
- insert: O(n)
- search: O(n)
- startsWith: O(n)

Space Complexity: O(n * c) (c = calls)
- 길이 3인 알파벳 소문자 문자열의 가짓수 : 26^3 = 17,576
- 길이 4인 알파벳 소문자 문자열의 가짓수 : 26^4 = 456,976
만약 n이 3 이하였다면, 3만 번의 call 동안 trie가 포화되어 공간 복잡도가 O(26 * n) = O(n) 이었을 것.
하지만 n이 2,000으로 충분히 크기 때문에 trie가 포화되지는 않을 것이므로, 공간 복잡도는 O(n * c).
*/
class Trie {

class Node {
public char val;
public boolean ends;
public HashMap<Character, Node> children;

Node() {
this.children = new HashMap<>();
}
}

public Node root;

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

public void insert(String word) {
Node curr = this.root;

for (char ch : word.toCharArray()) {
curr = curr.children.computeIfAbsent(ch, c -> new Node());
curr.val = ch;
}
curr.ends = true;
}

public boolean search(String word) {
Node curr = this.root;

for (char ch : word.toCharArray()) {
curr = curr.children.get(ch);
if (curr == null)
return false;
}
return curr.ends;
}

public boolean startsWith(String prefix) {
Node curr = this.root;

for (char ch : prefix.toCharArray()) {
curr = curr.children.get(ch);
if (curr == null)
return false;
}
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);
*/
33 changes: 33 additions & 0 deletions word-break/forest000014.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*

Time Complexity: O(s * L^2)
- L is max length of wordDict[i]
Space Complexity: O(s + w * L)
*/
class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
Set<String> wordSet = new HashSet<>();
int maxLen = 0;
for (String word : wordDict) {
wordSet.add(word);
maxLen = Math.max(maxLen, word.length());
}

boolean[] dp = new boolean[s.length() + 1];
dp[0] = true;

for (int i = 0; i < s.length(); i++) {
for (int j = 1; j <= maxLen; j++) {
int beginIdx = i - j + 1;
if (beginIdx < 0)
continue;
if (wordSet.contains(s.substring(beginIdx, i + 1)) && dp[beginIdx]) {
dp[i + 1] = true;
break;
}
}
}

return dp[s.length()];
}
}
Loading