Skip to content
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
18 changes: 18 additions & 0 deletions best-time-to-buy-and-sell-stock/dahyeong-yun.java

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🏷️ 알고리즘 패턴 분석

  • 패턴: Two Pointers, Greedy, Hash Map / Hash Set
  • 설명: 최적 매매가를 구하기 위해 한 번의 순회로 현재까지의 최저가와 최대 이익을 갱신하는 방식으로 해결한다. 전체적으로 한 방향 탐색과 간단한 상태 기억으로 구성된Greedy 패턴에 해당하며, 투 포인터와 유사한 양상을 보인다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(n) O(n)
Space O(1) O(1)

피드백: 최소값과 최대 이익을 한 번의 순회로 구하는 간단한 그리디 방식입니다. 추가 데이터 구조 없이 상수 공간으로 구현되어 있습니다.

개선 제안: 현재 구현이 적절해 보입니다.

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* TC : O(n)
* - 가격 배열 n-1 만큼 순회하므로 O(n)
* SC : O(1)
* - 상수 개의 변수만 사용하므로 O(1)
*/
class Solution {
public int maxProfit(int[] prices) {
int maxProfit = 0; // 안사는 것이 최선인 경우
int minPrice = prices[0]; // 첫번째 가격으로 사는 경우

for(int i=1; i<prices.length; i++) { // 다음 날 부터 차익이 있을 수 있음.
minPrice = Math.min(minPrice, prices[i]); // 최저가 갱신
maxProfit = Math.max(prices[i] - minPrice, maxProfit); // 최저가 기준 오늘 팔았을 때 이익 갱신
Comment on lines +13 to +14

@parkhojeong parkhojeong Jul 25, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

python의 경우엔 min, max가 오버헤드가 있어서 성능상 최적화 여지가 있는데 java는 min, max가 단순 삼항 연산자로 구현되어 있어서 큰 차이는 없는 거 같네요.

java max 구현체 링크입니다.
https://github.com/openjdk/jdk/blob/3412d4c0dd5250f14cc6fe594355bdf2ff976417/src/java.base/share/classes/java/lang/Math.java#L2023

}
return maxProfit;
}
}
24 changes: 24 additions & 0 deletions group-anagrams/dahyeong-yun.java

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🏷️ 알고리즘 패턴 분석

  • 패턴: Hash Map / Hash Set, Greedy, Divide and Conquer
  • 설명: 해시 맵을 사용해 같은 정렬 문자열을 키로 묶어 그룹화하므로 Hash Map 패턴이 핵심이다. 각 문자열을 정렬해 키를 만들고 맵에 넣는 방식은 간단한 분할/그룹화 개념으로 분류 가능하며, 키 생성 과정에서 정렬을 이용하는 부분은 전체 흐름의 핵심이다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(n * m log m) O(n * m log m)
Space O(n * m) O(n * m)

피드백: 각 문자열 길이를 m이라 두고, 모든 문자열에 대해 정렬을 수행하므로 시간 복잡도는 O(n * m log m)이고, 각 문자열의 문자 배열 및 해시맵이 추가 공간을 사용합니다.

개선 제안: 큰 입력에서 성능을 개선하려면 카운트 기반 키(26개 알파벳의 개수로 구성) 사용을 고려해 정렬 비용을 제거하는 방향을 생각해볼 수 있습니다.

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* input str의 길이가 n이고, 각 str 문자열의 길이를 m라 할 때
*
* TC : O(n * m log m)
* - n 번 순회할 때마다 각 단어 정렬에 m log m 만큼 소요되므로 O(n * m log m)
* SC : O(n * m)
* - n * m 만큼의 char 배열 공간을 key 값 생성으로 사용
* - 정답 Map 에서 입력 크기 n만큼의 공간 을 사용
* - 따라서 (n * m) + n 즉 O(n * m) 만큼의 공간 사용
*/
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> answer = new HashMap<>();

for(String str : strs) {
char[] c = str.toCharArray();
Arrays.sort(c);
String key = String.valueOf(c);
answer.computeIfAbsent(key, k -> new ArrayList<>()).add(str);
}

return new ArrayList<>(answer.values());
}
}
39 changes: 39 additions & 0 deletions word-break/dahyeong-yun.java

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🏷️ 알고리즘 패턴 분석

  • 패턴: Backtracking, Dynamic Programming, Hash Map / Hash Set
  • 설명: DFS로 가능한 단어 조합을 탐색하고, 이미 방문한 인덱스에서의 실패를 메모이제이션(imposible 배열)해 재탐색을 줄이는 형태가 Backtracking과 DP의 결합으로 보입니다. 단어 매칭 시 사전 단어를 반복 확인하는 방식은 느리지만, 문제 구조상 재귀 DFS와 부분해로 결과를 재사용하는 DP 성격이 섞여 있습니다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(n * m * k) O(?)
Space O(n) O(len)

피드백: 현재 DFS 기반으로 특정 입력에서 지수 시간 복잡도에 취약합니다. 불필요한 재탐색을 막기 위한 캐시가 존재하지만, 전체적인 경우의 수를 모두 탐색하는 경우가 발생할 수 있습니다.

개선 제안: 메모이제이션을 통해 각 인덱스에서의 결과를 저장하고, 단어 사전을 트라이나 해시 세트를 활용해 시작 위치에서의 매칭을 빠르게 검증하면 성능을 개선할 수 있습니다.

Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* n: 문자열 s의 길이, m: wordDict 단어 수, k: 단어의 평균 길이
* - TC: O(n * m * k) -> n개 인덱스 방문 × m개 단어 순회 × k 길이 문자열 비교
* - SC: O(n) -> 메모이제이션 배열 및 재귀 스택 깊이 O(n)
*/
class Solution {
String s;
int len = 0;
boolean[] imposible;
List<String> wordDict;

public boolean wordBreak(String s, List<String> wordDict) {
this.s = s;
this.len = s.length();
this.imposible = new boolean[len];
this.wordDict = wordDict;
return dfs(0);
}

public boolean dfs(int index) {
if(index == len) {
return true;
}

if(imposible[index]) return false;

for(String word : wordDict) {
int wordLength = word.length();
if(s.startsWith(word, index)) {
if(len >= index + wordLength) {
if(dfs(index + wordLength)) return true;
}
}
Comment on lines +29 to +33

@parkhojeong parkhojeong Jul 25, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

삼중 if 라서 살짝 리팩토링하면 가독성 챙겨볼 수 있을 거 같습니다.

Suggested change
if(s.startsWith(word, index)) {
if(len >= index + wordLength) {
if(dfs(index + wordLength)) return true;
}
}
if(!s.startsWith(word, index) || len < index + wordLength) continue;
if(dfs(index + wordLength)) return true;

}

imposible[index] = true;
return false;
}
}
Loading