Skip to content

[sangbeenmoon] WEEK 08 Solutions - #2820

Merged
parkhojeong merged 3 commits into
DaleStudy:mainfrom
sangbeenmoon:week08
Aug 15, 2026
Merged

[sangbeenmoon] WEEK 08 Solutions#2820
parkhojeong merged 3 commits into
DaleStudy:mainfrom
sangbeenmoon:week08

Conversation

@sangbeenmoon

@sangbeenmoon sangbeenmoon commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

답안 제출 문제

작성자 체크 리스트

  • Projects의 오른쪽 버튼(▼)을 눌러 확장한 뒤, Week를 현재 주차로 설정해주세요.
  • 문제를 모두 푸시면 프로젝트에서 StatusIn Review로 설정해주세요.
  • 코드 검토자 1분 이상으로부터 승인을 받으셨다면 PR을 병합해주세요.

검토자 체크 리스트

Important

본인 답안 제출 뿐만 아니라 다른 분 PR 하나 이상을 반드시 검토를 해주셔야 합니다!

  • 바로 이전에 올라온 PR에 본인을 코드 리뷰어로 추가해주세요.
  • 본인이 검토해야하는 PR의 답안 코드에 피드백을 주세요.
  • 토요일 전까지 PR을 병합할 수 있도록 승인해주세요.

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.

🏷️ 알고리즘 패턴 분석

clone-graph/sangbeenmoon.java
// Definition for a Node.

import java.util.ArrayList;
import java.util.Map;

/* 
class Node {
    public int val;
    public List<Node> neighbors;
    public Node() {
        val = 0;
        neighbors = new ArrayList<Node>();
    }
    public Node(int _val) {
        val = _val;
        neighbors = new ArrayList<Node>();
    }
    public Node(int _val, ArrayList<Node> _neighbors) {
        val = _val;
        neighbors = _neighbors;
    }
}
*/

class Solution {

    // <원본, 복제본>
    public Map<Node,Node> map = new HashMap<>();

    public Node cloneGraph(Node node) {
    
      if (node == null) {
        return null;
      }

      return dfs(node);
    }

    public Node dfs(Node origin) {
        if (map.containsKey(origin)) {
            return map.get(origin);
        }

        if (origin == null) {
            return null;
        }

        Node copied = new Node(origin.val);
        map.put(origin, copied);
        
        for (Node n : origin.neighbors) {
            Node neighbor = dfs(n);
            copied.neighbors.add(neighbor);
        }

        return copied;
    }
}
  • 패턴: Depth-First Search, Hash Map / Hash Set
  • 설명: 그래프를 깊이 우선으로 순회하며 각 노드를 복제하고, 원래 노드와 복제본 간 매핑을 HashMap으로 저장하여 이미 방문한 노드를 재사용합니다. 순회 시 재귀dfs로 이웃 노드를 방문하며 연결 관계를 재현합니다.

📊 시간/공간 복잡도 분석

복잡도
Time O(N + E)
Space O(N)

피드백: 맵으로 원본 노드와 복제본 노드를 매핑해 사이클이 있는 그래프에서도 중복 복제를 방지한다.

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

💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!

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.

🏷️ 알고리즘 패턴 분석

longest-common-subsequence/sangbeenmoon.java
class Solution {
    public int longestCommonSubsequence(String text1, String text2) {

        int dp[][] = new int[text1.length()][text2.length()];


        for(int i = 0; i < text1.length(); i++){
            if (text1.substring(0,i + 1).contains(String.valueOf(text2.charAt(0)))) {
                dp[i][0] = 1;
            }
        }

        for(int i = 0; i < text2.length(); i++){
            if (text2.substring(0,i + 1).contains(String.valueOf(text1.charAt(0)))) {
                dp[0][i] = 1;
            }
        }

        for(int i = 1; i < text1.length(); i++){
            for(int j = 1; j< text2.length(); j++){
                if(text1.charAt(i) == text2.charAt(j)){
                    dp[i][j] = dp[i-1][j-1] + 1;
                } else {
                    dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
                }
            }
        }
        
        return dp[text1.length() - 1][text2.length() - 1];
        

    }
}
  • 패턴: Dynamic Programming
  • 설명: 두 문자열의 최장 공통 부분 수열을 구하기 위해 이차원 DP 테이블을 채우는 방식으로 문제를 해결합니다. 이전 상태의 값을 이용해 현재 상태를 구성하는 전형적인 DP 패턴입니다.

📊 시간/공간 복잡도 분석

복잡도
Time O(n * m)
Space O(n * m)

피드백: 2차원 DP 배열을 사용해 모든 부분문제 결과를 저장한다.

개선 제안: 경계 초기화와 인덱스 접근을 명확히 하고, 공간을 줄이려면 한 행만 사용하는 방법도 있다.

💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!

@dalestudy

dalestudy Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

📊 sangbeenmoon 님의 학습 현황

이번 주 제출 문제

문제 난이도 유형 분석
clone-graph Medium ✅ 의도한 유형
longest-common-subsequence Medium ⚠️ 유형 불일치
longest-repeating-character-replacement Medium ✅ 의도한 유형
palindromic-substrings Medium ⚠️ 유형 불일치

누적 학습 요약

  • 풀이한 문제: 22 / 75개
  • 이번 주 유형 일치율: 50% (4문제 중 2문제 일치)

문제 풀이 현황

카테고리 진행도 완료
Matrix ■■■■■□□ 3 / 4 (Medium 3)
Dynamic Programming ■■■■□□□ 7 / 11 (Medium 7)
Array ■■■□□□□ 4 / 10 (Medium 4)
Heap ■■□□□□□ 1 / 3 (Medium 1)
Graph ■■□□□□□ 2 / 8 (Medium 2)
Tree ■■□□□□□ 3 / 14 (Medium 3)
String ■□□□□□□ 2 / 10 (Medium 2)
Binary □□□□□□□ 0 / 5 ← 아직 시작 안 함
Interval □□□□□□□ 0 / 5 ← 아직 시작 안 함
Linked List □□□□□□□ 0 / 6 ← 아직 시작 안 함

🤖 이 댓글은 GitHub App을 통해 자동으로 작성되었습니다.

🔢 API 사용량 (gpt-5-nano)
요청 입력 토큰 출력 토큰 합계 비용
1 1,920 198 2,118 $0.000175

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.

🏷️ 알고리즘 패턴 분석

longest-repeating-character-replacement/sangbeenmoon.java
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

class Solution {

    Map<Character, Integer> counterMap = new HashMap<>();

    public int characterReplacement(String s, int k) {
        
        int left = 0;
        int answer = 0;

        for (int right = 0; right < s.length(); right++){  
            if(counterMap.containsKey(s.charAt(right))){
           
                int cnt = counterMap.get(s.charAt(right));
                counterMap.put(s.charAt(right), cnt + 1);
            }
            else {
                counterMap.put(s.charAt(right), 1);
            }

            while (!isCounterOK(k)) {
                char l = s.charAt(left);
                int cnt = counterMap.get(l);
                if (cnt == 1) counterMap.remove(l);
                else counterMap.put(l, cnt - 1);
                left++;
            }
            answer = Math.max(answer, right - left + 1);
        }

        return answer;
    }

    public boolean isCounterOK(int k) {
        int maxCount = 0;
        int totalCount = 0;
        for (Entry<Character, Integer> entry : counterMap.entrySet()) {
            maxCount = Math.max(maxCount, entry.getValue());
            totalCount = totalCount + entry.getValue();
        }
        return totalCount - maxCount <= k;
    }
}
  • 패턴: Two Pointers, Hash Map / Hash Set, Greedy, Sliding Window
  • 설명: left와 right 두 포인터로 구간을 확장/축소하며 최적의 길이를 찾는다. 해시 맵으로 문자 빈도수를 추적하고, 전체 길이에서 최다 빈도수를 빼서 허용 횟수 k를 만족하는지 판단한다. 이때 윈도우의 최대 길이를 계속 갱신하므로 슬라이딩 윈도우와 그리디의 결합으로 풀이된다.

📊 시간/공간 복잡도 분석

복잡도
Time O(n)
Space O(AlphabetSize)

피드백: 윈도우의 크기를 유지하며 최대 빈도 문자를 활용한다.

개선 제안: Counter 갱신 로직을 간결화하고, maxCount를 window 밖에서도 관리하는 방법을 고려해볼 수 있다.

💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!

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.

🏷️ 알고리즘 패턴 분석

palindromic-substrings/sangbeenmoon.py
class Solution:
    def countSubstrings(self, s: str) -> int:
        dp = [[0] * (len(s) + 1) for _ in range(len(s) + 1)]

        def isPalindrome(start, end) -> bool:

            if end - start == 0:
                return True

            if end - start == 1 :
                return s[start] == s[end]

            if dp[start][end] == 1:
                return True

            if dp[start][end] == -1:
                return False    

            if s[start] == s[end]:
                return isPalindrome(start+1, end-1)    

            return False

        answer = 0

        for i in range(len(s) - 1, -1, -1):
            for j in range(i,len(s)):
                if isPalindrome(i,j):                    
                    dp[i][j] = 1
                    answer += 1
                else:
                    dp[i][j] = -1

        return answer
                
  • 패턴: Dynamic Programming
  • 설명: 문자열의 부분 문자열이 회문인지 여부를 DP로 저장해가며(메모이제이션) 중복 계산을 피하고 전체 부분 문자열을 탐색합니다. 주어진 풀이에서 dp 테이블로 회문 여부를 기록하고, 역순으로 시작점과 끝점을 늘려가며 결과를 누적합니다.

📊 시간/공간 복잡도 분석

복잡도
Time O(n^2)
Space O(n^2)

피드백: isPalindrome 재귀와 DP 표를 섞어 부분 문자열의 회문 여부를 저장한다.

개선 제안: 현재 구현은 Python 구문과 DP 표 초기화가 다소 비효율적일 수 있어, 확정된 확장 방법으로 단순화하는 것을 고려해볼 수 있다.

💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!

@parkhojeong parkhojeong left a comment

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.

수고하셨습니다.

Comment on lines +15 to +31
if(counterMap.containsKey(s.charAt(right))){

int cnt = counterMap.get(s.charAt(right));
counterMap.put(s.charAt(right), cnt + 1);
}
else {
counterMap.put(s.charAt(right), 1);
}

while (!isCounterOK(k)) {
char l = s.charAt(left);
int cnt = counterMap.get(l);
if (cnt == 1) counterMap.remove(l);
else counterMap.put(l, cnt - 1);
left++;
}
answer = Math.max(answer, right - left + 1);

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.

돌려보니 성능이 좋은 편은 아니라서 조금 더 최적화 시도해보셔도 좋을 거 같습니다.

Comment on lines +37 to +45
public boolean isCounterOK(int k) {
int maxCount = 0;
int totalCount = 0;
for (Entry<Character, Integer> entry : counterMap.entrySet()) {
maxCount = Math.max(maxCount, entry.getValue());
totalCount = totalCount + entry.getValue();
}
return totalCount - maxCount <= k;
}

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.

이쪽에서 오버헤드가 살짝 있어 보이네요. 단순하게 빈도 배열만 사용해보시는 건 어떨까요?

@parkhojeong
parkhojeong merged commit 7be9266 into DaleStudy:main Aug 15, 2026
3 checks passed
@github-project-automation github-project-automation Bot moved this from In Review to Completed in 리트코드 스터디 8기 Aug 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Completed

Development

Successfully merging this pull request may close these issues.

2 participants