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
60 changes: 60 additions & 0 deletions combination-sum/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, Depth-First Search, Greedy
  • 설명: 백트래킹으로 모든 조합을 탐색하고, 합이 타깃과 같아지면 정답에 추가합니다. 각 재귀에서 후보를 고정된 시작 위치부터 반복하며, 재귀호출로 깊이 우선 탐색을 수행합니다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(H(N, M) * M) O(K * N^K)
Space O(H(N, M) * M) O(K)

피드백: 백트래킹으로 중복 조합을 고려하되 시작 인덱스를 i로 고정하여 중복 조합을 제거하고 합이 타깃을 넘으면 가지치기를 한다.

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* [풀이 개요]
* - 시간복잡도 : O(H(N, M) * M)
* - 공간복잡도 : O(H(N, M) * M) (정답 배열 제외 시 O(M))
*/
class Solution {
/**
* [문제 풀이 아이디어]
* - candidates 배열의 수를 조합해서 target을 만드는 조합을 중복되는 조합 없이 찾아야 함.
* - 각 원소는 중복이 될 수 있음. 이 때문에 candidates을 여러번 반복해서 찾아야 함. 조합이 되는 배열의 길이가 동적이므로 재귀적으로 확인해야 할 듯.
* - 시공간복잡도의 경우, 중복 조합의 개수를 계산해야 하는 건 알겠는데, 계산이 직관적으로는 이해가 잘 안됨. O(H(N, M) * M)
*/
private List<List<Integer>> answer = new ArrayList<>();

public List<List<Integer>> combinationSum(int[] candidates, int target) {
backtracking(0, 0, target, candidates, new ArrayList<>());
return answer;
}

/**
* [시뮬레이션: 인덱스 & Sum 추적]
* 형식: [인덱스 조합] (계산 과정) = 현재Sum
* * * 시작 (Sum = 0)
* ├── [0] (+2) = Sum: 2
* │ ├── [0, 0] (+2) = Sum: 4
* │ │ ├── [0, 0, 0] (+2) = Sum: 6
* │ │ │ └── [0, 0, 0, 0] (+2) = Sum: 8 ❌ (Over 7)
* │ │ └── [0, 0, 1] (+3) = Sum: 7 ★ 정답 [2, 2, 3]
* │ ├── [0, 1] (+3) = Sum: 5
* │ │ └── [0, 1, 1] (+3) = Sum: 8 ❌ (앞의 2로 못 돌아감)
* │ └── [0, 2] (+6) = Sum: 8 ❌
* │
* ├── [1] (+3) = Sum: 3 <-- 이제 이전 인덱스인 0번(값 2)은 영구 제외
* │ ├── [1, 1] (+3) = Sum: 6
* │ │ └── [1, 1, 1] (+3) = Sum: 9 ❌
* │ └── [1, 2] (+6) = Sum: 9 ❌
* │
* ├── [2] (+6) = Sum: 6
* │ └── [2, 2] (+6) = Sum: 12 ❌
* │
* └── [3] (+7) = Sum: 7 ★ 정답 [7]
*/
public void backtracking(int start, int sum, int target, int[] candidates, List<Integer> list) {
if(sum == target) {
answer.add(new ArrayList<>(list));
return; // 🎯 정답을 찾았으므로 즉시 탈출 (효율성 증가)
}

if(sum > target) {
return;
}

// 🎯 i = start 및 재귀 인자 i로 변경하여 주석의 '중복 조합' 로직 완성
for(int i = start; i < candidates.length; i++) {
list.add(candidates[i]);
backtracking(i, sum + candidates[i], target, candidates, list);
list.remove(list.size() - 1);
}
}
}
61 changes: 61 additions & 0 deletions decode-ways/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.

🏷️ 알고리즘 패턴 분석

  • 패턴: Dynamic Programming, Top-Down / Memoization
  • 설명: 주어진 코드는 한 자리/두 자리 파싱 가능 여부를 재귀로 탐색하고, 중복을 dp 배열로 저장하는 메모이제이션 다이나믹 프로그래밍 패턴을 사용합니다. 부분 문제의 해를 합쳐 최종 해를 구하는 특성도 보입니다.

📊 시간/공간 복잡도 분석

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

피드백: 상태를 start 인덱스로 두고 한 자리 또는 두 자리로 파싱 가능한 경우를 재귀적으로 합산한다. DP 배열로 중복 계산을 방지한다.

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* [풀이 개요]
* - 시간복잡도 : O(n)
* - 공간복잡도 : O(n)
*/
class Solution {
/**
* [문제 풀이 아이디어]
* - 한 글자로 파싱이 되는 경우의 수와 두 글자로 파싱이 되는 경우 수를 합하면 될 것 같음
* - 시간복잡도는 각 인덱스를 처음 한번 들린 이 후로는 dp 배열에서 O(1)에 리턴하므로 O(n).
* - 공간복잡도는 문자열 길이 만큼의 dp 배열을 생성하므로 O(n)
*/
public int numDecodings(String s) {
int len = s.length();
int[] dp = new int[len + 1];
Arrays.fill(dp, -1);
return count(0, s, len, dp);
}

/**
* [시뮬레이션]
* Case : 226
* count(0, 226, {-1,-1,-1})
* += count(1, 226, {-1,-1,-1}) return 2 / 2
* += count(2, 226, {-1,-1,-1}) return 1 / 2 2
* += count(3, 226, {-1,-1,-1}) return 1 / 2 2 6
* += 0 (4 > limit)
* += count(3, 226, {-1,-1,-1}) return 1 / 2 26 / cashing
* += count(2, 226, {-1,-1,-1}) return 1 / 22 / cashing
* += count(3, 226, {-1,-1,-1}) return 1 / 22 6 / cashing
* = 1 + 2 = 3
*/
public int count(int start, String s, int limitIndex, int[] dp) {
if(start == limitIndex) {
return 1;
}
// 0으로 시작할 수 없음
if(s.charAt(start) == '0') {
return 0;
}

if(dp[start] != -1) {
return dp[start];
}

int totalWays = 0;

if(start + 1 <= limitIndex) {
totalWays += count(start + 1, s, limitIndex, dp);
}

if(start + 2 <= limitIndex) {
String numStr = s.substring(start, start+2);
if(Integer.parseInt(numStr) <= 26) {
totalWays += count(start + 2, s, limitIndex, dp);
}
}
dp[start] = totalWays;
return totalWays;
}
}
25 changes: 25 additions & 0 deletions maximum-subarray/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.

🏷️ 알고리즘 패턴 분석

  • 패턴: Greedy
  • 설명: 카데인 알고리즘으로 연속 부분 배열 합의 최대를 구하는 문제로, 현 위치까지의 최적 부분해를 누적하고 큰 값을 선택하는 방식이다. O(n) 시간, O(1) 공간의 특징도 있다.

📊 시간/공간 복잡도 분석

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

피드백: 현재 값과 누적합의 최댓값을 갱신하며 최댓값을 유지한다.

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* [풀이 개요]
* - 시간복잡도 : O(n)
* - 공간복잡도 : O(1)
*/
class Solution {
/**
* [문제 풀이 아이디어]
* - 연속된 부분 배열 합의 최대를 구하는 문제. 즉, 카데인 알고리즘을 떠올릴 수 있음
* - 수 배열을 한번 순회 하므로 시간복잡도는 O(n)
* - 별도 공간 할당이 없으므로 공간복잡도는 O(1)
*/
public int maxSubArray(int[] nums) {
int max = nums[0];
int current = nums[0];

int len = nums.length;
for(int i=1; i<len; i++) {
current = Math.max(nums[i], current + nums[i]);
max = Math.max(current, max);
}

return max;
}
}
46 changes: 46 additions & 0 deletions number-of-1-bits/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.

🏷️ 알고리즘 패턴 분석

  • 패턴: Bit Manipulation, Greedy, Divide and Conquer, Dynamic Programming, Hash Map / Hash Set, Two Pointers, Sliding Window, Fast & Slow Pointers, BFS, DFS, Backtracking, Union Find, Trie, Heap / Priority Queue, Monotonic Stack
  • 설명: 코드는 비트 연산으로 1의 개수를 구하는 두 구현을 포함합니다. 비트 조작(Bit Manipulation) 패턴이 핵심이며, 제2 구현은 반복을 이용한 진법 변환 개념으로도 해석될 수 있습니다.

📊 시간/공간 복잡도 분석

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

피드백: 128비트까지의 정수에 대해서 비트 카운트 연산을 수행한다. 보조 풀이도 함께 첨부되어 있다.

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* [풀이 개요]
* - 시간복잡도 : O(1)
* - 공간복잡도 : O(1)
*/
class Solution {
public int hammingWeight(int n) {
return Integer.bitCount(n);
}

/** 참고
@IntrinsicCandidate
public static int bitCount(int i) {
// HD, Figure 5-2
i = i - ((i >>> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
i = (i + (i >>> 4)) & 0x0f0f0f0f;
i = i + (i >>> 8);
i = i + (i >>> 16);
return i & 0x3f;
}
*/

/**
* [문제 풀이 아이디어]
* - 10진수를 2진수로 표현했을 때 1의 갯 수를 세야함.
* - 10진수를 2로 나눈 몫이 0이 될 때까지 나누고, 각각의 나머지를 역으로 적으면 2진수가 됨.
* - 따라서 각 나눗셈의 나머지가 1인 경우를 카운트 할 수 있음
* - 진법 변환 예시
* - 10 % 2 = 5, 0 - 2^0
* - 5 % 2 = 2, 1 - 2^1
* - 2 % 2 = 1, 0 - 2^2
* - 1 % 2 = 0, 1 - 2^3
* - 10 => 1010
* - int는 32비트 자료형으로 최대 32번 반복하므로 시간복잡도는 상수시간으로 봐도 무방, O(1)
* - 별도 공간이 유의미한 공간할당을 하고 있지 않으므로 공간복잡도는 0(1)
*/
public int hammingWeight(int n) {
int count = 0;
while(n > 0) {
count += n % 2;
n /= 2;
}
return count;
}
}
43 changes: 43 additions & 0 deletions valid-palindrome/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
  • 설명: 문자열 양 끝에서 문자 비교를 진행하는 투 포인터 방식으로, 좌우를 동시에 진행하며 조건에 맞게 스킵하거나 비교하는 구성이므로 투 포인터 패턴에 속합니다.

📊 시간/공간 복잡도 분석

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

피드백: 비 알파벳/숫자 문자는 건너뛰고 소문자로 비교하여 대칭 여부를 판단한다.

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* [풀이 개요]
* - 시간복잡도 : O(n)
* - 공간복잡도 : O(1)
*/
class Solution {
/**
* [문제 풀이 아이디어]
* - 주어진 문자열의 길이가 최대 10^5 이므로 10^8 까지 통과할 수 있다고 가정할 때, 시간복잡도는 O (n log n)까지 가능해 보임
* - 문자열 s의 시작과 끝 인덱스가 각각 x, y 라고 할 때 s[x] == s[y], s[x+1] == s[y-1], s[x+2] == s[y-2], s[x+n] == s[y-n] (n은 문자열 중간 인덱스 까지) 와 같이 검증할 수 있음.
* - 즉 투포인터 형태가 될 수 있어 보임.
* - 다만 알파벳이 아닌 문자는 제외하고 판단해야 하므로 포인터가 정확히 같은 값을 x, y에서 빼는 형태가 될 수는 없고, 비교 대상이 아닌 인덱스를 넘어가서 다음에 판단해야 함.
* - 이렇게 순회할 경우 문자열 길이 n의 1/2 를 순회하므로 시간복잡도는 O(n) 이 됨.
* - 매 char 변수 이외에 추가 공간이 필요치 않으므로 공간복잡도는 O(1) 이 됨.
*/
public boolean isPalindrome(String s) {
int len = s.length();
if(len == 1) return true;

int left = 0;
int right = len - 1;

while(left < right) {
char leftChar = Character.toLowerCase(s.charAt(left));
char rightChar = Character.toLowerCase(s.charAt(right));

// 문자가 아닌 경우 다음 인덱스 확인
if(!Character.isLetterOrDigit(leftChar)) {
left++;
} else if(!Character.isLetterOrDigit(rightChar)) {
right--;

// 동일한 경우 다음 인덱스 확인
} else if(leftChar == rightChar) {
left++;
right--;
} else {
return false;
}
}
return true;
}
}
Loading