Skip to content

[eunhwa99] Week 5 #841

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 7 commits into from
Jan 8, 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
55 changes: 55 additions & 0 deletions best-time-to-buy-and-sell-stock/eunhwa99.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// 풀이 방법
// 1. 인덱스 x까지의 최소값을 저장하는 배열 1개와, 인덱스 x부터의 최대값을 저장하는 배열 1개를 만든다.
// 2. 1번에서 만든 두 배열에 값을 채운다.
// 3. 두 배열을 각각 인덱스 별로 차를 구하고, 그 중 최댓값을 구한다.

// 시간 복잡도
// O(n) : 배열을 2번 순회하므로 O(n)이다.
// 공간 복잡도
// O(n) : 최소값과 최대값을 저장하는 배열을 만들었으므로 O(n)이다.

class Solution {
public int maxProfit(int[] prices) {
int len = prices.length;
int[] minArr = new int[len];
int[] maxArr = new int[len];

for(int i=0;i<len;i++){
if(i==0){
minArr[i] = prices[i];
maxArr[len-i-1] = prices[len-i-1];
}else{
minArr[i] = Math.min(minArr[i-1], prices[i]);
maxArr[len-i-1] = Math.max(maxArr[len-i], prices[len-i-1]);
}
}

int result = 0;
for(int i=0;i<len;i++){
result = Math.max(result, maxArr[i]-minArr[i]);
}
return result;
}
}


// 2nd solution
// 시간 복잡도: O(n)
// 공간 복잡도: O(1)

class Solution{
public int maxProfit(int[] prices){
int len = prices.length;
int buy = prices[0];
int result = 0;

for(int i=1;i<len;i++){
if(prices[i]<buy){ // 더 저렴한 주식이 있으므로
buy = prices[i]; // 이 주식을 산다.
}else{
result = Math.max(result, prices[i]-buy); // 현재 주식을 팔았을 때 이득이 더 크다면 판다.
}
}
return result;
}
}
48 changes: 48 additions & 0 deletions encode-and-decode-strings/eunhwa99.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import java.util.ArrayList;
import java.util.List;
// n: 문자열 리스트 길이, m: 각 문자열의 길이.

// 시간 복잡도
// Encoding: O(n * m)
// Decoding: O(n * m)
// 공간 복잡도
// Encoding: O(n * m),
// Decoding: O(n * m)
class Solution {

// 받아온 string 들을 한 문자열로 합침
// (문자열길이)#(문자열) 형식
public String encode(List<String> strs) {
StringBuilder encodedStr = new StringBuilder();
for (String str : strs) {
encodedStr.append(str.length()).append('#').append(str);
}
return encodedStr.toString();
}

// Decodes a single string to a list of strings
public List<String> decode(String s) {
List<String> result = new ArrayList<>();
int i = 0;

while (i < s.length()) {

int j = i;
while (s.charAt(j) != '#') { // # 문자 찾기
j++;
}

// 문자열 길이 추출
int length = Integer.parseInt(s.substring(i, j));

// 위에서 구한 문자열 길이만큼 문자열 추출
result.add(s.substring(j + 1, j + 1 + length));

// i 위치 변경
i = j + 1 + length;
}

return result;
}

}
31 changes: 31 additions & 0 deletions group-anagrams/eunhwa99.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

// 해결법
// 1. 배열 안의 월소들을 순회한다.
// 2. 각 원소에 대하여 문자열을 정렬한 후, hashmap에 넣는다. 이 때 hashMap 자료구조는 <String, List<String>> 형태로 만든다.

// 시간 복잡도:
// 1. 크기가 m인 문자열을 정렬할 때 O(mlogm)이 소요
// 2. 배열의 크기가 n 이므로 순회하는데 O(n)
// 3. hashmap 삽입은 O(1)
// 위 사실들을 조합하면 총 O(nmlogm)이 소요된다.
// 참고로, 전체 배열 크기는 최대 10^4 이고, 각 문자열의 길이는 최대 100이므로, 위와 같이 접근할 경우, 최대 10^6의 시간 복잡도를 가진다.

// 공간 복잡도: hashmap 크기만큼 사용 -> O(nm)

class Solution{
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<>();
for(String str: strs){
char[] charArr = str.toCharArray();
Arrays.sort(charArr);

map.computeIfAbsent(String.valueOf(charArr), key -> new ArrayList<>()).add(str);
}
return map.values().stream().toList();
}
}
35 changes: 35 additions & 0 deletions implement-trie-prefix-tree/eunhwa99.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import java.util.HashMap;
import java.util.Map;

// insert 시, 문자열의 prefix를 다 Map에 저장하고, 해당 문자열은 prefix 이므로 boolean false 로 설정
// prefix가 아닌 온전한 문자열 삽입은 true 로 저장

// search 시, Map에 해당 단어가 있는지 확인하고, boolean 값이 true 인지 확인
// startsWith는 그냥 Map 에 해당 문자열이 있는지 확인하면 된다.

// 공간 복잡도: Map 크기 -> O(N)
// 시간 복잡도: 전체 호출 수 * String 길이 -> O(N*M)
// 참고) 최대 시간 복잡도 : 2000 * 3*10^4 = 6*10^7
class Trie {

Map<String,Boolean> stringSet;
public Trie() {
stringSet = new HashMap<>();
}

public void insert(String word) {
for(int i=0;i<word.length();i++){
stringSet.putIfAbsent(word.substring(0, i), false);
}
stringSet.put(word, true);
}

public boolean search(String word) {
return stringSet.containsKey(word) && stringSet.get(word)==true;
}

public boolean startsWith(String prefix) {

return stringSet.containsKey(prefix);
}
}
36 changes: 36 additions & 0 deletions word-break/eunhwa99.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import java.util.List;


// 풀이
// dfs + memo
// memo[i] = true/false : i 인덱스에서 시작해서 wordDict에 존재하는 모든 부분문자열 찾을 수 있는 경로가 있는지 유무
//시간 복잡도: O(n*n) = start~end(재귀) + start~end(반복문)
// 공간 복잡도: O(n) - 재귀 깊이

class Solution {

public boolean wordBreak(String s, List<String> wordDict) {
return dfs(0, s.length(), s, wordDict, new Boolean[s.length()]);

}
public boolean dfs(int start, int len, String s, List<String> wordDict, Boolean[] memo){
if(start==len){
return true;
}

if(memo[start]!=null) return memo[start];

for(int end=start+1; end<=len;end++){
if(wordDict.contains(s.substring(start, end))){
if(dfs(end, len, s, wordDict, memo)){
memo[start] = true;
return true;
}
}
}

memo[start]=false;
return false;

}
}
Loading