From 802470ef93e382aa507c1b35f314dfbe42ca1f3c Mon Sep 17 00:00:00 2001 From: ekgns33 Date: Mon, 6 Jan 2025 16:00:30 +0900 Subject: [PATCH 1/5] feat : best-time-to-buy-and-sell-stock --- best-time-to-buy-and-sell-stock/ekgns33.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/ekgns33.java diff --git a/best-time-to-buy-and-sell-stock/ekgns33.java b/best-time-to-buy-and-sell-stock/ekgns33.java new file mode 100644 index 000000000..7789293ed --- /dev/null +++ b/best-time-to-buy-and-sell-stock/ekgns33.java @@ -0,0 +1,11 @@ +class Solution { + public int maxProfit(int[] prices) { + int minPrice = Integer.MAX_VALUE; + int maxProfit = 0; + for(int i = 0; i < prices.length; i++) { + minPrice = Math.min(minPrice, prices[i]); + maxProfit = Math.max(maxProfit, prices[i] - minPrice); + } + return maxProfit; + } +} From 8b0b142f24c48f23e76601438e51936f5aa48242 Mon Sep 17 00:00:00 2001 From: ekgns33 Date: Mon, 6 Jan 2025 16:00:42 +0900 Subject: [PATCH 2/5] feat : encode-and-decode-strings --- encode-and-decode-strings/ekgns33.java | 36 ++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 encode-and-decode-strings/ekgns33.java diff --git a/encode-and-decode-strings/ekgns33.java b/encode-and-decode-strings/ekgns33.java new file mode 100644 index 000000000..628bd5ce9 --- /dev/null +++ b/encode-and-decode-strings/ekgns33.java @@ -0,0 +1,36 @@ +class Solution { + public String encode(List strs) { + StringBuilder res = new StringBuilder(); + for (String s : strs) { + res.append(s.length()).append('|').append(s); + } + return res.toString(); + } + + + /* + * number + | + string + * read number until | + * move pointer, read substring + * + * tc : O(n) when n is the length of encoded string + * sc : O(1) + * */ + public List decode(String str) { + List res = new ArrayList<>(); + int start = 0; + while (start < str.length()) { + int cur = start; + //read until | + while (str.charAt(cur) != '|') { + cur++; + } + int length = Integer.parseInt(str.substring(start, cur)); + start = cur + 1; + cur = start + length; + res.add(str.substring(start, cur)); + start = cur; + } + return res; + } +} From 27f6370d4f40a5c860727ca518ea15efe4638217 Mon Sep 17 00:00:00 2001 From: ekgns33 Date: Mon, 6 Jan 2025 16:00:52 +0900 Subject: [PATCH 3/5] feat : group-anagrams --- group-anagrams/ekgns33.java | 45 +++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 group-anagrams/ekgns33.java diff --git a/group-anagrams/ekgns33.java b/group-anagrams/ekgns33.java new file mode 100644 index 000000000..15a9db2cd --- /dev/null +++ b/group-anagrams/ekgns33.java @@ -0,0 +1,45 @@ +/** + + input : array of strings + output : grouped anagrams + + ex) eat ate tea > same group + + solution 1) brute force + ds : hashmap + algo : sort + generate Key by sorting string O(nlogn) + + save to hashmap + + tc : O(m* nlogn) when m is length of array, n is max length of string + sc : O(m) + + solutino 2) better? + cannot optimize m times read + how about generating key + + sort = nlogn + read = n << use frequency + 26 * n + tc : O(m * (26 * n)) ~= O(mn) + sc : O(m * 26) ~= O(m) + */ + +class Solution { + public List> groupAnagrams(String[] strs) { + Map> map = new HashMap<>(); + int n = strs.length; + for(String str : strs) { + int l = str.length(); + char[] freq = new char[26]; + for(int i = 0; i < l; i++) { + freq[str.charAt(i) - 'a']++; + } + String key = new String(freq); + map.putIfAbsent(key, new ArrayList<>()); + map.get(key).add(str); + } + return List.copyOf(map.values()); + } +} From 97db55dc3021a572f65154990005135d67bf14b7 Mon Sep 17 00:00:00 2001 From: ekgns33 Date: Tue, 7 Jan 2025 13:58:50 +0900 Subject: [PATCH 4/5] feat : implement-trie-prefix-tree --- implement-trie-prefix-tree/ekgns33.java | 54 +++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 implement-trie-prefix-tree/ekgns33.java diff --git a/implement-trie-prefix-tree/ekgns33.java b/implement-trie-prefix-tree/ekgns33.java new file mode 100644 index 000000000..ec3d3e934 --- /dev/null +++ b/implement-trie-prefix-tree/ekgns33.java @@ -0,0 +1,54 @@ +class Trie { + + class Node { + boolean isEnd; + Node[] childs = new Node[26]; + Node() {} + } + + private Node root; + + public Trie() { + this.root = new Node(); + } + + // O(m) when m is the length of word + public void insert(String word) { + Node curN = this.root; + for(char c : word.toCharArray()) { + if(curN.childs[c-'a'] == null) { + curN.childs[c-'a'] = new Node(); + } + curN = curN.childs[c-'a']; + } + //end + curN.isEnd = true; + } + // O(k) when k is the length of searching word + public boolean search(String word) { + Node curN = this.root; + for(char c : word.toCharArray()) { + if(curN.childs[c-'a'] == null) return false; + curN = curN.childs[c-'a']; + } + return curN.isEnd; + } + + // O(k) when k is the length of prefix + public boolean startsWith(String prefix) { + Node curN = this.root; + for(char c : prefix.toCharArray()) { + if(curN.childs[c-'a'] == null) return false; + curN = curN.childs[c-'a']; + } + 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); + */ From 4119a969b80b202097b4464d98d84951e6f36f20 Mon Sep 17 00:00:00 2001 From: ekgns33 Date: Tue, 7 Jan 2025 13:59:02 +0900 Subject: [PATCH 5/5] feat : word-break --- word-break/ekgns33.java | 94 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 word-break/ekgns33.java diff --git a/word-break/ekgns33.java b/word-break/ekgns33.java new file mode 100644 index 000000000..8db868057 --- /dev/null +++ b/word-break/ekgns33.java @@ -0,0 +1,94 @@ +/** + input : string s and array of strings + output : return true if s can be segmented into one or more words in dictionary + constraints : + 1) same word can be used multiple times + 2) every word in dictionary is unique + 3) s.length [1, 300] + 4) length of tokens in dictionary [1, 20] + + ex) + leetcode >> leet code + applepenapple >> apple pen + applepenapple >> apple applepen + + + solution 1) bruteforce + for each character c, check if word exists in dictionary + that the first letter is c + + match string + move to next + unmatch + next word + + >> get all the combinations + O(n * m * k) + n is the length of string s, + m is number of tokens, + k is length of token + + tc : O (nmk) (300 * 1000 * 20) ~= 6 * 10^6 < 1sec + sc : O (mk) + + solution 2) optimize? heuristic? + + using trie will reduce tc + for each character: + get all substring substr(i, j) + search trie + + tc : O(n^2 + m*k) + + solution 3) dp + + let dp[i] true if possible to build s which length is i + with segemented tokens + + build HashSet for tokens + iterate i from 1 to n + iterate j from 0 to i-1 + dp[i] = dp[j] & substr(j,i) presents // substr O(n) + if true break; + + tc : O(n^3 + m*k) + */ +class Solution { + public boolean wordBreak(String s, List wordDict) { + Set dict = new HashSet<>(wordDict); + boolean[] dp = new boolean[s.length() + 1]; + dp[0] = true; + for(int i = 1; i < dp.length; i++) { + for(int j = 0; j < i; j++) { + if(dp[j] && dict.contains(s.substring(j, i))){ + dp[i] = true; + break; + } + } + } + return dp[dp.length - 1]; + } +} + + +// class Solution1 { +// public boolean wordBreak(String s, List wordDict) { +// Map> tokens = new HashMap<>(); +// for(String word : wordDict) { +// tokens.putIfAbsent(word.charAt(word.length()-1), new ArrayList<>()); +// tokens.get(word.charAt(word.length()-1)).add(word); +// } +// boolean[] dp = new boolean[s.length()+1]; +// dp[0] = true; +// for(int i = 1; i < dp.length; i++) { +// List token = tokens.get(s.charAt(i-1)); +// if(token == null) {dp[i] = false; continue;} +// for(String word : token) { +// if(i - word.length() < 0) continue; +// dp[i] = dp[i-word.length()] && s.substring(i-word.length(), i).equals(word); +// if(dp[i]) break; +// } +// } +// return dp[dp.length-1]; +// } +// }