<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>hi_soap.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Wed, 02 Sep 2026 02:33:44 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>hi_soap.log</title>
            <url>https://velog.velcdn.com/images/hi_soap/profile/dfb4c39c-d5a8-48d4-8633-af3ea1720216/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. hi_soap.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/hi_soap" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[택배상자_복습]]></title>
            <link>https://velog.io/@hi_soap/%ED%83%9D%EB%B0%B0%EC%83%81%EC%9E%90%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@hi_soap/%ED%83%9D%EB%B0%B0%EC%83%81%EC%9E%90%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Wed, 02 Sep 2026 02:33:44 GMT</pubDate>
            <description><![CDATA[<p><strong>2026.09.02</strong></p>
<h2 id="문제-풀이">문제 풀이</h2>
<h3 id="1차-실행-오류">1차 실행 오류</h3>
<hr>
<p><code>50.0/100</code></p>
<p>실패 및 런타임 에러</p>
<hr>
<pre><code class="language-java">import java.util.Deque;
import java.util.ArrayDeque;

class Solution {
    public int solution(int[] orders) {
        int cur = 1;
        int answer = 0;
        Deque&lt;Integer&gt; sub = new ArrayDeque&lt;&gt;();

        int idx = 0;
        while(true) {
            if (idx &gt;= orders.length || cur &gt; orders[idx] &amp;&amp; sub.peek() &gt; orders[idx]) {
                break;
            }
            if (cur == orders[idx]) { // 현재 꺼낸 상자가 이번 순서인 경우
                answer++;
                idx++;
            }
            else if (!sub.isEmpty() &amp;&amp; sub.peek() == orders[idx]) { 
                // 보조 컨테이너 벨트의 상자가 이번 순서인 경우
                answer++;
                idx++;
                sub.pop();
            }
            else { // 현재 꺼낸 상자가 이번 순서가 아닌 경우
                sub.push(cur); // 보조 컨테이너 벨트에 삽입
            }
            cur++;
        }

        return answer;
    }
}</code></pre>
<h3 id="나의-코드">나의 코드</h3>
<hr>
<p><strong><em>소요 시간: 38분</em></strong>
<strong><em>시간 복잡도: $O(n)$</em></strong></p>
<hr>
<pre><code class="language-java">import java.util.Deque;
import java.util.ArrayDeque;

class Solution {
    public int solution(int[] orders) {
        int cur = 1;
        int answer = 0;
        Deque&lt;Integer&gt; sub = new ArrayDeque&lt;&gt;();

        int idx = 0;
        while(true) {
            if (!sub.isEmpty() &amp;&amp; sub.peek() == orders[idx]) {
                sub.pop();
                answer++;
                idx++;
            }
            else sub.push(cur++);
            if (idx &gt;= orders.length || !sub.isEmpty() &amp;&amp; sub.peek() &gt; orders[idx]) break;
        }

        return answer;
    }
}</code></pre>
<h3 id="ai-코드">AI 코드</h3>
<hr>
<p><strong><em>시간 복잡도: $O(n)$</em></strong></p>
<hr>
<p><strong><em>코드 분석</em></strong></p>
<p>전체적인 구조는 동일하다.</p>
<p>바깥쪽 <code>for</code>문을 이용해서 <code>orders</code>의 길이만큼 반복하고
안쪽의 <code>while</code>문을 이용해서 서브 컨테이너 벨트에서 
택배 상자를 빼는 작업을 분할해서 진행한 코드이다.</p>
<hr>
<pre><code class="language-java">import java.util.Deque;
import java.util.ArrayDeque;

class Solution {
    public int solution(int[] orders) {
        int n = orders.length;
        Deque&lt;Integer&gt; sub = new ArrayDeque&lt;&gt;(); // 보조 컨테이너
        int idx = 0;                             // 다음에 실어야 할 주문 위치

        for (int box = 1; box &lt;= n; box++) {
            sub.push(box);                       // 컨테이너 벨트에서 상자 하나 올림
            // 꼭대기가 원하는 상자인 동안 계속 트럭에 실음
            while (idx &lt; n &amp;&amp; !sub.isEmpty() &amp;&amp; sub.peek().intValue() == orders[idx]) {
                sub.pop();
                idx++;
            }
        }
        return idx; // 실은 상자 개수 = 처리한 주문 개수
    }
}</code></pre>
<h2 id="문제-풀이-후기">문제 풀이 후기</h2>
<p>나의 코드에서 <code>answer</code>와 <code>idx</code>가 가리키는 값이 항상 일치하기 때문에
둘 중 하나만 사용하면 된다.</p>
<p>1차에서 실패한 코드를 보고 로직이 너무 꼬여 있다는 생각이 들었다.
좀 더 단순화해서 풀 수 있는 방법이 없을까? 고민하다가
서브 컨테이너 벨트에 계속 다 넣고, 들어가 있는 상자가 현재 실어야 하는 순서의 상자이면 빼는 방식으로 코드를 작성하였다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[압축_복습]]></title>
            <link>https://velog.io/@hi_soap/%EC%95%95%EC%B6%95%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@hi_soap/%EC%95%95%EC%B6%95%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Tue, 01 Sep 2026 03:24:57 GMT</pubDate>
            <description><![CDATA[<p><strong>2026.09.01</strong></p>
<h2 id="문제-풀이">문제 풀이</h2>
<h3 id="나의-코드">나의 코드</h3>
<hr>
<p><strong><em>소요 시간: 2시간 16분</em></strong>
<strong><em>시간 복잡도: $O(n)$</em></strong></p>
<hr>
<pre><code class="language-java">import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;

class Solution {
    public int[] solution(String msg) {
        int order = 1;
        Map &lt;String, Integer&gt; map = new HashMap&lt;&gt;();
        List&lt;Integer&gt; list = new ArrayList&lt;&gt;();

        for (char c = &#39;A&#39;; c &lt;= &#39;Z&#39;; c++) { // 해시맵에 알파벳 저장
            map.put(Character.toString(c), order++);
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i &lt; msg.length(); i++) {
            char c = msg.charAt(i);
            sb.append(c);
            if (map.get(sb.toString()) == null) { // 해시맵에 해당 단어가 존재하지 않을 때
                map.put(sb.toString(), order++);
                list.add(map.get(sb.substring(0, sb.length() - 1)));
                sb.setLength(0);
                sb.append(c);
            }
        }
        if (sb.length() &gt; 0) {
            list.add(map.get(sb.toString()));
        }
        return list.stream().mapToInt(Integer::intValue).toArray();
    }
}</code></pre>
<h3 id="ai-코드">AI 코드</h3>
<hr>
<p><strong><em>시간 복잡도: $O(n)$</em></strong></p>
<hr>
<p><strong><em>코드 분석</em></strong></p>
<p><code>substring</code> 대신에 <code>prev</code>, <code>cur</code> 변수를 이용하여 
반복당 문자열 객체 1개 생성을 감소하였다.</p>
<hr>
<pre><code class="language-java">import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;

class Solution {
    public int[] solution(String msg) {
        Map&lt;String, Integer&gt; dict = new HashMap&lt;&gt;();
        int index = 1;
        for (char c = &#39;A&#39;; c &lt;= &#39;Z&#39;; c++) { // 사전 초기화
            dict.put(String.valueOf(c), index++);
        }

        List&lt;Integer&gt; answer = new ArrayList&lt;&gt;();
        StringBuilder sb = new StringBuilder();
        int prev = 0; // 직전까지 매칭된 문자열의 색인

        for (int i = 0; i &lt; msg.length(); i++) {
            char c = msg.charAt(i);
            sb.append(c);
            Integer cur = dict.get(sb.toString());

            if (cur == null) {          // 사전에 없음 → 등록하고 직전 색인 출력
                dict.put(sb.toString(), index++);
                answer.add(prev);
                sb.setLength(0);
                sb.append(c);           // 마지막 글자부터 다시 시작
                prev = dict.get(sb.toString());
            } else {                    // 사전에 있음 → 색인만 갱신하고 계속 확장
                prev = cur;
            }
        }
        answer.add(prev);               // 남은 문자열 처리

        return answer.stream().mapToInt(Integer::intValue).toArray();
    }
}</code></pre>
<h2 id="문제-풀이-후기">문제 풀이 후기</h2>
<p>이전에는 풀었던 문제임에도 불구하고 이번에는 해결하지 못하였다.</p>
<p>프로젝트의 막바지라 약 2주동안 코딩 테스트를 쉬었던 상태에서 시작해서
감을 잃었나 싶다. 역시 뭐든 꾸준히 하는 것이 가장 중요하다고 생각된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[땅따먹기_복습]]></title>
            <link>https://velog.io/@hi_soap/%EB%95%85%EB%94%B0%EB%A8%B9%EA%B8%B0%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@hi_soap/%EB%95%85%EB%94%B0%EB%A8%B9%EA%B8%B0%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Sun, 16 Aug 2026 04:43:23 GMT</pubDate>
            <description><![CDATA[<p><strong>2026.08.16</strong></p>
<h2 id="문제-풀이">문제 풀이</h2>
<h3 id="1차-실행-오류">1차 실행 오류</h3>
<hr>
<p><code>0.0/100</code></p>
<p>시간 초과 오류</p>
<hr>
<p><strong><em>시간 초과 원인 분석</em></strong></p>
<p>행의 개수가 100,000개 이하인 배열에 DFS를 사용한 것이 원인</p>
<hr>
<pre><code class="language-java">class Solution {
    private int answer = 0;
    int solution(int[][] land) {
        dfs(land, 0, 0, 0);

        return answer;
    }
    private void dfs(int land[][], int row, int col, int sum) {
        answer = Math.max(answer, sum);
        if (row &gt;= land.length) {
            return;
        }

        for (int i = 0; i &lt; land[row].length; i++) {
            if (i == col) {
                continue;
            }
            dfs(land, row + 1, col, sum + land[row][i]);    
        }
    }
}</code></pre>
<h3 id="나의-코드">나의 코드</h3>
<hr>
<p><strong><em>소요 시간: 45분</em></strong>
<strong><em>시간 복잡도: $O(n)$</em></strong></p>
<hr>
<p><strong><em>코드 분석</em></strong></p>
<p>이전 행과 현재 행 사이에서 가장 큰 값을 찾아 저장하여 가장 큰 값을 찾아냄</p>
<hr>
<pre><code class="language-java">class Solution {
    int solution(int[][] land) {
        int row = land.length;
        int col = land[0].length;

        int[][] dp = new int[row][col];

        for (int i = 0; i &lt; col; i++) {
            dp[0][i] = land[0][i];
        }

        for (int i = 1; i &lt; row; i++) {
            for (int j = 0; j &lt; col; j++) {
                for (int k = 0; k &lt; col; k++) {
                    if (j == k) continue;
                    dp[i][j] = Math.max(dp[i][j], dp[i - 1][k] + land[i][j]);
                }
            }
        }
        int answer = 0;
        for (int i = 0; i &lt; col; i++) {
            answer = Math.max(answer, dp[row - 1][i]);
        }

        return answer;
    }
}</code></pre>
<h3 id="ai-코드">AI 코드</h3>
<hr>
<p><strong><em>시간 복잡도: $O(n)$</em></strong></p>
<hr>
<p><strong><em>코드 분석</em></strong></p>
<p>기존 나의 코드에서 3중 <code>for</code>문을 사용하던 방식에서
이전 행의 첫 번째로 큰 값과 두 번째로 큰 값을 미리 구해서
이번 행의 가장 큰 값과 더하는 방식을 사용하여 개선함</p>
<hr>
<pre><code class="language-java">class Solution {
    int solution(int[][] land) {
        int n = land.length, c = land[0].length;
        int[] prev = land[0].clone();

        for (int i = 1; i &lt; n; i++) {
            // 직전 행의 1등 값/인덱스와 2등 값
            int best = Integer.MIN_VALUE, second = Integer.MIN_VALUE, bestIdx = -1;
            for (int j = 0; j &lt; c; j++) {
                if (prev[j] &gt; best) { second = best; best = prev[j]; bestIdx = j; }
                else if (prev[j] &gt; second) { second = prev[j]; }
            }

            int[] cur = new int[c];
            for (int j = 0; j &lt; c; j++) {
                cur[j] = land[i][j] + (j == bestIdx ? second : best);  // 같은 열이면 2등을 사용
            }
            prev = cur;   // 행 하나만 굴린다 → 공간 O(1)
        }

        int answer = Integer.MIN_VALUE;
        for (int v : prev) answer = Math.max(answer, v);
        return answer;
    }
}</code></pre>
<h2 id="문제-풀이-후기">문제 풀이 후기</h2>
<p>DP 문제가 너무 어렵다고 느껴진다.
AI 분석을 해 본 결과 다른 자료구조 문제에 비해 풀어 보았던 문항 수가
현저히 적어서 손에 익지 않았다는 것이 그 원인이다.</p>
<p>나의 학습법을 보면 많은 경험을 토대로 익숙해지는 것이 가장 수월하게
배울 수 있는 길이라고 생각한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[n진수 게임_복습]]></title>
            <link>https://velog.io/@hi_soap/n%EC%A7%84%EC%88%98-%EA%B2%8C%EC%9E%84-1h6h6qgt</link>
            <guid>https://velog.io/@hi_soap/n%EC%A7%84%EC%88%98-%EA%B2%8C%EC%9E%84-1h6h6qgt</guid>
            <pubDate>Sat, 15 Aug 2026 03:23:22 GMT</pubDate>
            <description><![CDATA[<p><strong>2026.08.15</strong></p>
<h2 id="문제-풀이">문제 풀이</h2>
<h3 id="나의-코드">나의 코드</h3>
<hr>
<p><strong><em>소요 시간: 16분</em></strong>
<strong><em>시간 복잡도: $O(t·m)$</em></strong></p>
<hr>
<pre><code class="language-java">class Solution {
    public String solution(int n, int t, int m, int p) {
        StringBuilder sb = new StringBuilder();

        int idx = 0;
        int order = 1;
        while(sb.length() &lt; t) {
            String number = Integer.toString(idx, n);
            number = number.toUpperCase();
            for (int i = 0; i &lt; number.length(); i++) {
                if (order == p) {
                    sb.append(number.charAt(i));
                    if (sb.length() == t) {
                        break;
                    }
                }
                order = order % m + 1;
            }
            idx++;
        }

        return sb.toString();
    }
}</code></pre>
<h3 id="ai-코드">AI 코드</h3>
<hr>
<p><strong><em>시간 복잡도: $O(t·m)$</em></strong></p>
<hr>
<p><strong><em>코드 분석</em></strong></p>
<p>필요한 n진수 전부를 미리 <code>tube</code>에 저장해두고,
튜브의 순서에 필요한 수만 따로 빼서 저장</p>
<hr>
<pre><code class="language-java">class Solution {
    public String solution(int n, int t, int m, int p) {
        // 1) 필요한 만큼만 튜브 생성: 마지막으로 읽을 위치는 (t-1)*m + p ≤ t*m
        StringBuilder tube = new StringBuilder();
        for (int i = 0; tube.length() &lt; t * m; i++) {
            tube.append(Integer.toString(i, n).toUpperCase());
        }

        // 2) p번째(1-based)부터 m칸씩 t개 뽑기
        StringBuilder answer = new StringBuilder();
        for (int i = p - 1; answer.length() &lt; t; i += m) {
            answer.append(tube.charAt(i));
        }
        return answer.toString();
    }
}</code></pre>
<h2 id="문제-풀이-후기">문제 풀이 후기</h2>
<p>수학적인 계산이 코드 길이에 얼마나 큰 영향을 주는지 알 수 있었다.
필요한 n진수를 미리 계산하는 과정을 통해서, 
각 숫자마다 <code>String</code>을 2개씩 할당하는 과정을 없앴다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[주식가격_복습]]></title>
            <link>https://velog.io/@hi_soap/%EC%A3%BC%EC%8B%9D%EA%B0%80%EA%B2%A9%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@hi_soap/%EC%A3%BC%EC%8B%9D%EA%B0%80%EA%B2%A9%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Fri, 14 Aug 2026 01:19:40 GMT</pubDate>
            <description><![CDATA[<p><strong>2026.08.14</strong></p>
<h2 id="문제-풀이">문제 풀이</h2>
<h3 id="나의-코드">나의 코드</h3>
<hr>
<p><strong><em>소요 시간: 37분</em></strong>
<strong><em>시간 복잡도: $O(n)$</em></strong></p>
<hr>
<pre><code class="language-java">import java.util.Deque;
import java.util.ArrayDeque;

class Solution {
    public int[] solution(int[] prices) {
        int[] answer = new int[prices.length];
        Deque&lt;int[]&gt; stack = new ArrayDeque&lt;&gt;();

        int cnt = -1;
        for (int i = 0; i &lt; prices.length; i++) {
            cnt++;
            while(!stack.isEmpty() &amp;&amp; stack.peek()[1] &gt; prices[i]) {
                int[] s = stack.pop();
                answer[s[0]] = cnt - s[0];
            }
            stack.push(new int[]{i, prices[i]});      
        }
        while(!stack.isEmpty()) {
            int[] s = stack.pop();
            answer[s[0]] = cnt - s[0];
        }

        return answer;
    }
}</code></pre>
<h3 id="ai-코드">AI 코드</h3>
<hr>
<p><strong><em>시간 복잡도: $O(n)$</em></strong></p>
<hr>
<p><strong><em>코드 분석</em></strong></p>
<p>전체적인 알고리즘은 동일하나, <code>cnt</code>를 사용하지 않고 <code>i</code>로 대체,
값을 저장하지 않고, 인덱스만 저장하여 <code>prices[stack.peek()]</code>로 대체하여
코드의 불필요한 변수 사용을 줄였다.</p>
<hr>
<pre><code class="language-java">class Solution {
    public int[] solution(int[] prices) {
        int n = prices.length;
        int[] answer = new int[n];
        int[] stack = new int[n];   // 아직 가격이 떨어지지 않은 시점들의 인덱스
        int top = -1;

        for (int i = 0; i &lt; n; i++) {
            // i초에 가격이 떨어졌다면, 그보다 비쌌던 시점들은 여기서 기간 확정
            while (top &gt;= 0 &amp;&amp; prices[stack[top]] &gt; prices[i]) {
                int j = stack[top--];
                answer[j] = i - j;
            }
            stack[++top] = i;
        }
        // 끝까지 떨어지지 않은 시점들
        while (top &gt;= 0) {
            int j = stack[top--];
            answer[j] = n - 1 - j;
        }
        return answer;
    }
}</code></pre>
<h2 id="문제-풀이-후기">문제 풀이 후기</h2>
<p>대체 가능한 필요없는 변수를 정리해서
해당 작업을 거친 AI 코드는 훨씬 길이가 짧고 가독성이 좋다.
코드 작성 후에 깔끔하게 마무리 하는 습관을 들여야 할 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[k진수에서 소수 개수 구하기]]></title>
            <link>https://velog.io/@hi_soap/k%EC%A7%84%EC%88%98%EC%97%90%EC%84%9C-%EC%86%8C%EC%88%98-%EA%B0%9C%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0-rg87vepk</link>
            <guid>https://velog.io/@hi_soap/k%EC%A7%84%EC%88%98%EC%97%90%EC%84%9C-%EC%86%8C%EC%88%98-%EA%B0%9C%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0-rg87vepk</guid>
            <pubDate>Wed, 12 Aug 2026 02:49:30 GMT</pubDate>
            <description><![CDATA[<p><strong>2026.08.12</strong></p>
<h2 id="문제-풀이">문제 풀이</h2>
<h3 id="1차-실행-오류">1차 실행 오류</h3>
<hr>
<p><code>86.9/100</code></p>
<p>런타임 에러</p>
<hr>
<p><strong><em>런타임 에러 원인 분석</em></strong></p>
<p><code>n = 797161</code>, <code>k = 3</code> (<code>n</code>을 <code>k</code>진수로 변환하면 1111111111111에 해당함)
<code>int</code>로 전부 담을 수 없음</p>
<hr>
<pre><code class="language-java">class Solution {
    public int solution(int n, int k) {
        int cnt = 0;
        String baseK = Integer.toString(n, k);

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i &lt; baseK.length(); i++) {
            char c = baseK.charAt(i);
            if (c == &#39;0&#39;) {
                if (!sb.isEmpty() &amp;&amp; isPrime(Integer.parseInt(sb.toString()))) {
                    cnt++;
                }
                sb.setLength(0);
            }
            else {
                sb.append(c);
            }
        }
        if (!sb.isEmpty() &amp;&amp; isPrime(Integer.parseInt(sb.toString()))) {
            cnt++;
        }
        return cnt;
    }
    private boolean isPrime(int n) {
        if (n &lt;= 1) {
            return false;
        }
        if (n == 2) {
            return true;
        }
        int limit = (int)Math.sqrt(n);
        for (int i = 2; i &lt;= limit; i++) {
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }
}</code></pre>
<h3 id="나의-코드">나의 코드</h3>
<hr>
<p><strong><em>소요 시간: 42분</em></strong>
<strong><em>시간 복잡도: $O(√(10^{log_k n}))$</em></strong></p>
<hr>
<pre><code class="language-java">class Solution {
    private boolean isPrime(long n) {
        if (n &lt;= 1) {
            return false;
        }
        if (n == 2) {
            return true;
        }
        int limit = (int)Math.sqrt(n);
        for (int i = 2; i &lt;= limit; i++) {
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }
    public int solution(int n, int k) {        
        int cnt = 0;
        String baseK = Integer.toString(n, k);           
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i &lt; baseK.length(); i++) {
            char c = baseK.charAt(i);
            if (c == &#39;0&#39;) {
                if (!sb.isEmpty() &amp;&amp; isPrime(Long.parseLong(sb.toString()))) {
                    cnt++;
                }
                sb.setLength(0);
            }
            else {
                sb.append(c);
            }
        }
        if (!sb.isEmpty() &amp;&amp; isPrime(Long.parseLong(sb.toString()))) {
            cnt++;
        }
        return cnt;
    }
}</code></pre>
<h3 id="ai-코드">AI 코드</h3>
<hr>
<p><strong><em>시간 복잡도: $O(√(10^{log_k n}))$</em></strong></p>
<hr>
<p><strong><em>코드 분석</em></strong></p>
<p>전체적인 구조는 동일하나 <code>split(&quot;0&quot;)</code>을 사용해서
길었던 <code>if/else</code>문을 단번에 정리했음</p>
<p><code>sb.isEmpty()</code>는 Java 15에서 추가된 메서드이기 때문에
이전 버전에서는 오류가 발생할 수 있음.</p>
<hr>
<pre><code class="language-java">class Solution {
    public int solution(int n, int k) {
        int cnt = 0;
        for (String s : Integer.toString(n, k).split(&quot;0&quot;)) {
            if (!s.isEmpty() &amp;&amp; isPrime(Long.parseLong(s))) cnt++;
        }
        return cnt;
    }

    private boolean isPrime(long num) {
        if (num &lt;= 1) return false;
        if (num &lt;= 3) return true;          // 2, 3
        if (num % 2 == 0) return false;     // 짝수 선제거

        for (long i = 3; i * i &lt;= num; i += 2) {   // 홀수만 검사
            if (num % i == 0) return false;
        }
        return true;
    }
}</code></pre>
<h2 id="문제-풀이-후기">문제 풀이 후기</h2>
<p><code>split()</code>과 같은 문자열 메서드를 활용할 생각을 하지 못해봤다.
내가 이미 알고 있는 지식들만 하더라도 다방면으로 응용이 가능하며, 
엄청난 활용이 가능하다는 것을 깨달을 수 있었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[더 맵게_복습]]></title>
            <link>https://velog.io/@hi_soap/%EB%8D%94-%EB%A7%B5%EA%B2%8C%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@hi_soap/%EB%8D%94-%EB%A7%B5%EA%B2%8C%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Tue, 11 Aug 2026 03:04:27 GMT</pubDate>
            <description><![CDATA[<p><strong>2026.08-11</strong></p>
<h2 id="문제-풀이">문제 풀이</h2>
<h3 id="나의-코드">나의 코드</h3>
<hr>
<p><strong><em>소요 시간: 49분</em></strong>
<strong><em>시간 복잡도: $O(nlogn)$</em></strong></p>
<hr>
<pre><code class="language-java">import java.util.PriorityQueue;

class Solution {
    public int solution(int[] scoville, int K) {
        int cnt = 0;

        PriorityQueue&lt;Integer&gt; pq = new PriorityQueue&lt;&gt;();
        for (int k : scoville) {
            pq.add(k);
        }

        while(pq.peek() &lt; K) {
            if (pq.size() &lt; 2) {
                return -1;
            }
            int key1 = pq.poll();
            int key2 = pq.poll();
            pq.add(key1 + key2 * 2);
            cnt++;
        }

        return cnt;
    }
}</code></pre>
<h3 id="ai-코드">AI 코드</h3>
<hr>
<p><strong><em>시간 복잡도: $O(nlogn)$</em></strong></p>
<hr>
<p><strong><em>코드 분석</em></strong></p>
<pre><code class="language-java">List&lt;Integer&gt; list = Arrays.stream(scoville).boxed().collect(Collectors.toList());</code></pre>
<ol>
<li><code>.stream()</code>을 이용해 <code>scoville[]</code> 원소가 하나씩 흘러가는 통로를 만듦</li>
<li><code>boxed()</code>를 이용해 <code>IntStream</code>을 <code>Integer</code> 객체로 포장함</li>
<li><code>.collect</code>를 이용해 흘러가는 원소들을 실제 컬렉션에 모아 담음</li>
</ol>
<hr>
<pre><code class="language-java">PriorityQueue&lt;Integer&gt; pq = new PriorityQueue&lt;&gt;(list);   // O(n) heapify</code></pre>
<p><code>add</code>를 n번 호출 시, 힙 생성 비용은 <code>O(n log n)</code>이지만, 
컬렉션을 한번에 받아 <code>O(n)</code>으로 생성이 가능함.</p>
<hr>
<pre><code class="language-java">import java.util.Arrays;
import java.util.List;
import java.util.PriorityQueue;
import java.util.stream.Collectors;

class Solution {
    public int solution(int[] scoville, int K) {
        List&lt;Integer&gt; list = Arrays.stream(scoville).boxed().collect(Collectors.toList());
        PriorityQueue&lt;Integer&gt; pq = new PriorityQueue&lt;&gt;(list);   // O(n) heapify

        int cnt = 0;
        while (pq.peek() &lt; K) {
            if (pq.size() &lt; 2) return -1;

            int first = pq.poll();
            int second = pq.poll();
            long mixed = (long) first + (long) second * 2;       // 오버플로 차단
            pq.add((int) Math.min(mixed, Integer.MAX_VALUE));    // K 이상이면 값 자체는 무의미
            cnt++;
        }
        return cnt;
    }
}</code></pre>
<h2 id="문제-풀이-후기">문제 풀이 후기</h2>
<p>자동 정렬을 해주는 <code>TreeMap</code>으로 해결해보려 했으나 값의 삽입 및 삭제가 용이하지 않아 부적합하다고 판단했음.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[뒤에 있는 큰 수 찾기_복습]]></title>
            <link>https://velog.io/@hi_soap/%EB%92%A4%EC%97%90-%EC%9E%88%EB%8A%94-%ED%81%B0-%EC%88%98-%EC%B0%BE%EA%B8%B0%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@hi_soap/%EB%92%A4%EC%97%90-%EC%9E%88%EB%8A%94-%ED%81%B0-%EC%88%98-%EC%B0%BE%EA%B8%B0%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Sun, 09 Aug 2026 05:04:58 GMT</pubDate>
            <description><![CDATA[<p><strong>2026.08.09</strong></p>
<h2 id="문제-풀이">문제 풀이</h2>
<h3 id="나의-코드">나의 코드</h3>
<hr>
<p><strong><em>소요 시간: 14분</em></strong>
<strong><em>시간 복잡도: $O(n)$</em></strong></p>
<hr>
<pre><code class="language-java">import java.util.Deque;
import java.util.ArrayDeque;

class Solution {
    public int[] solution(int[] numbers) {
        int len = numbers.length;
        int[] result = new int[len];

        Deque&lt;int[]&gt; stack = new ArrayDeque&lt;&gt;();
        for (int i = 0; i &lt; len; i++) {
            while(!stack.isEmpty() &amp;&amp; numbers[i] &gt; stack.peek()[1]) {
                int[] arr = stack.pop();
                result[arr[0]] = numbers[i];
            }
            stack.push(new int[]{ i, numbers[i] });
        }
        while(!stack.isEmpty()) {
            int[] arr = stack.pop();
            result[arr[0]] = -1;
        }

        return result;
    }
}</code></pre>
<h3 id="ai-코드">AI 코드</h3>
<hr>
<p><strong><em>시간 복잡도: $O(n)$</em></strong></p>
<hr>
<p><strong><em>코드 분석</em></strong></p>
<p><strong>단조 감소 스택(monotonic stack)</strong>을 사용한 동일한 알고리즘이지만,
하나의 배열과 <code>top</code> 변수를 사용하여, 
원소마다 배열 객체를 생성하는 나의 코드의 단점을 개선하였다.</p>
<hr>
<pre><code class="language-java">class Solution {
    public int[] solution(int[] numbers) {
        int n = numbers.length;
        int[] answer = new int[n];
        int[] stack = new int[n];   // 인덱스만 저장하는 배열 스택
        int top = 0;                // 스택 크기

        for (int i = 0; i &lt; n; i++) {
            while (top &gt; 0 &amp;&amp; numbers[stack[top - 1]] &lt; numbers[i]) {
                answer[stack[--top]] = numbers[i];
            }
            stack[top++] = i;
        }
        while (top &gt; 0) {
            answer[stack[--top]] = -1;
        }

        return answer;
    }
}</code></pre>
<h2 id="문제-풀이-후기">문제 풀이 후기</h2>
<p>가장 값이 적게 나가는 배열 활용을 1차로 생각해보고, 
불가능하다고 생각되면 그 때 라이브러리를 활용해야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[모음 사전_복습]]></title>
            <link>https://velog.io/@hi_soap/%EB%AA%A8%EC%9D%8C-%EC%82%AC%EC%A0%84%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@hi_soap/%EB%AA%A8%EC%9D%8C-%EC%82%AC%EC%A0%84%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Sat, 08 Aug 2026 06:22:25 GMT</pubDate>
            <description><![CDATA[<p><strong>2026.08.08</strong></p>
<h2 id="문제-풀이">문제 풀이</h2>
<h3 id="나의-코드">나의 코드</h3>
<hr>
<p><strong><em>소요 시간: 1시간</em></strong>
<strong><em>시간 복잡도: $O(1)$</em></strong></p>
<hr>
<pre><code class="language-java">class Solution {
    private String[] alphabet = { &quot;A&quot;, &quot;E&quot;, &quot;I&quot;, &quot;O&quot;, &quot;U&quot; };
    private int ans = 0;
    private int cnt = 0;
    public int solution(String word) {
        dfs(&quot;&quot;, word);

        return ans;
    }
    private void dfs(String s, String word) {
        if (s.length() == 5) {
            return;
        }
        for (int i = 0; i &lt; alphabet.length; i++) {
            cnt++;
            if ((s + alphabet[i]).equals(word)) {
                ans = cnt;
                return;
            }
            dfs(s + alphabet[i], word);
        }
    }
}</code></pre>
<h3 id="ai-코드">AI 코드</h3>
<hr>
<p><strong><em>시간 복잡도: $O(1)$</em></strong></p>
<hr>
<p><strong><em>코드 분석</em></strong></p>
<p><img src="https://velog.velcdn.com/images/hi_soap/post/7240dbfa-95ff-43fc-9c8e-cf708c1633d8/image.png" alt=""></p>
<p>수학적인 규칙을 사용하여 각 자릿수마다 가중치를 두고, 한번의 순회로 끝냄</p>
<hr>
<pre><code class="language-java">class Solution {
    public int solution(String word) {
        int[] weight = { 781, 156, 31, 6, 1 };
        String alphabet = &quot;AEIOU&quot;;
        int answer = 0;

        for (int i = 0; i &lt; word.length(); i++) {
            answer += alphabet.indexOf(word.charAt(i)) * weight[i] + 1;
        }

        return answer;
    }
}</code></pre>
<h2 id="문제-풀이-후기">문제 풀이 후기</h2>
<p>기본적인 DFS 문제였는데 
너무 어렵게 생각해서 이전에 풀었던 코드를 참고해서 해결했다.</p>
<p>수학적인 규칙을 찾으려 했으나, 찾지 못해서 DFS로 해결했다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[방문 길이_복습]]></title>
            <link>https://velog.io/@hi_soap/%EB%B0%A9%EB%AC%B8-%EA%B8%B8%EC%9D%B4%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@hi_soap/%EB%B0%A9%EB%AC%B8-%EA%B8%B8%EC%9D%B4%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Fri, 07 Aug 2026 04:10:24 GMT</pubDate>
            <description><![CDATA[<p><strong>2026.08.07</strong></p>
<h2 id="문제-풀이">문제 풀이</h2>
<h3 id="1차-실행-오류">1차 실행 오류</h3>
<hr>
<p><code>10/100</code></p>
<p>실패</p>
<hr>
<p><strong><em>실패 원인 분석</em></strong></p>
<pre><code class="language-java">for (int j = 0; j &lt; reversedArr.length; j++) {
    reversedArr[j] = arr[arr.length - j - 1];
}</code></pre>
<p>에서 잘못된 인덱스 값을 넣고 있던 것이 원인</p>
<hr>
<pre><code class="language-java">import java.util.Set;
import java.util.HashSet;
import java.util.Arrays;

class Solution {
    public int solution(String dirs) {
        int x = 0;
        int y = 0;
        int[] before = new int[2];
        int[] after = new int[2];
        int[] arr = new int[4];
        int[] reversedArr = new int[4];
        Set&lt;String&gt; set = new HashSet&lt;&gt;();

        for (int i = 0; i &lt; dirs.length(); i++) {
            before[0] = x;
            before[1] = y;
            char dir = dirs.charAt(i);

            switch(dir) {
                case &#39;L&#39;: {
                    x = (x &gt; -5 ? x - 1 : -5);
                    break;
                }
                case &#39;R&#39;: {
                    x = (x &lt; 5 ? x + 1 : 5);
                    break;
                }
                case &#39;U&#39;: {
                    y = (y &lt; 5 ? y + 1 : 5);
                    break;
                }
                case &#39;D&#39;: {
                    y = (y &gt; -5 ? y - 1 : -5);
                    break;
                }
            }
            after[0] = x;
            after[1] = y;
            arr[0] = before[0];
            arr[1] = before[1];
            arr[2] = after[0];
            arr[3] = after[1];

            for (int j = 0; j &lt; reversedArr.length; j++) {
                reversedArr[j] = arr[arr.length - j - 1];
            }

            if (arr[0] == arr[2] &amp;&amp; arr[1] == arr[3]) {
                continue;
            }
            set.add(Arrays.toString(arr));
            set.add(Arrays.toString(reversedArr));
        }
        return set.size() / 2;
    }
}</code></pre>
<h3 id="나의-코드">나의 코드</h3>
<hr>
<p><strong><em>소요 시간: 59분</em></strong>
<strong><em>시간 복잡도: $O(N)$</em></strong></p>
<hr>
<pre><code class="language-java">import java.util.Set;
import java.util.HashSet;
import java.util.Arrays;

class Solution {
    public int solution(String dirs) {
        int x = 0;
        int y = 0;
        int[] before = new int[2];
        int[] after = new int[2];
        int[] arr = new int[4];
        int[] reversedArr = new int[4];
        Set&lt;String&gt; set = new HashSet&lt;&gt;();

        for (int i = 0; i &lt; dirs.length(); i++) {
            before[0] = x;
            before[1] = y;
            char dir = dirs.charAt(i);

            switch(dir) {
                case &#39;L&#39;: {
                    x = (x &gt; -5 ? x - 1 : -5);
                    break;
                }
                case &#39;R&#39;: {
                    x = (x &lt; 5 ? x + 1 : 5);
                    break;
                }
                case &#39;U&#39;: {
                    y = (y &lt; 5 ? y + 1 : 5);
                    break;
                }
                case &#39;D&#39;: {
                    y = (y &gt; -5 ? y - 1 : -5);
                    break;
                }
            }
            after[0] = x;
            after[1] = y;
            arr[0] = before[0];
            arr[1] = before[1];
            arr[2] = after[0];
            arr[3] = after[1];

            reversedArr[0] = arr[2];
            reversedArr[1] = arr[3];
            reversedArr[2] = arr[0];
            reversedArr[3] = arr[1];

            if (arr[0] == arr[2] &amp;&amp; arr[1] == arr[3]) { // 이동하지 않았을 때
                continue;
            }
            set.add(Arrays.toString(arr));
            set.add(Arrays.toString(reversedArr));
        }
        return set.size() / 2;
    }
}</code></pre>
<h3 id="ai-코드">AI 코드</h3>
<hr>
<p><strong><em>시간 복잡도: $O(N)$</em></strong></p>
<hr>
<p><strong><em>코드 분석</em></strong></p>
<p>로직 자체는 나의 코드와 유사하다.</p>
<p>그러나 <code>Set</code>에 저장할 때에는 바로 문자열 형태로 만들어서 저장하기 때문에
<code>arr[]</code>, <code>reversedArr[]</code>를 사용할 필요가 없다.</p>
<p><code>before[]</code>, <code>after[]</code> 또한 배열이 아닌 변수를 그대로 사용하고,
값의 비교 없이 해당 값이 이탈했는지 하지 않았는지만을 판별한다.</p>
<hr>
<pre><code class="language-java">import java.util.HashSet;
import java.util.Set;

class Solution {
    public int solution(String dirs) {
        Set&lt;String&gt; visited = new HashSet&lt;&gt;();
        int x = 0;
        int y = 0;

        for (char c : dirs.toCharArray()) {
            int nx = x;
            int ny = y;

            switch (c) {
                case &#39;U&#39; -&gt; ny++;
                case &#39;D&#39; -&gt; ny--;
                case &#39;L&#39; -&gt; nx--;
                case &#39;R&#39; -&gt; nx++;
            }

            if (nx &lt; -5 || nx &gt; 5 || ny &lt; -5 || ny &gt; 5) continue; // 좌표 평면 이탈

            // 같은 길을 양방향으로 저장 → 왕복해도 1개로 취급
            visited.add(x + &quot;,&quot; + y + &quot;,&quot; + nx + &quot;,&quot; + ny);
            visited.add(nx + &quot;,&quot; + ny + &quot;,&quot; + x + &quot;,&quot; + y);

            x = nx;
            y = ny;
        }

        return visited.size() / 2;
    }
}</code></pre>
<h2 id="문제-풀이-후기">문제 풀이 후기</h2>
<p>이미 풀어봐서 익숙한 문제라 그런지 모르겠지만, 전체적인 코드 구조에 대한 알고리즘을 짜는 데에는 큰 어려움이 없다.</p>
<p>그러나 코드가 너무 난잡하다는 문제가 있다.
AI 코드처럼 개선의 여지가 분명함에도 문제점을 인식하지 못하고 있다.</p>
<p>잘 짜여진 코드들을 보면서 나의 코드가 어느 부분이 개선 여지가 있는지
판단할 수 있는 눈을 길러야 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[뉴스 클러스터링_복습]]></title>
            <link>https://velog.io/@hi_soap/%EB%89%B4%EC%8A%A4-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0%EB%A7%81%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@hi_soap/%EB%89%B4%EC%8A%A4-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0%EB%A7%81%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Wed, 05 Aug 2026 05:34:07 GMT</pubDate>
            <description><![CDATA[<p><strong>2026.08.05</strong></p>
<h2 id="문제-풀이">문제 풀이</h2>
<h3 id="나의-코드">나의 코드</h3>
<hr>
<p><strong><em>소요 시간: 1시간 42분</em></strong>
<strong><em>시간 복잡도: $O(n)$</em></strong></p>
<hr>
<pre><code class="language-java">import java.util.Map;
import java.util.HashMap;

class Solution {
    public int solution(String str1, String str2) {
        Map&lt;String, Integer&gt; map1 = new HashMap&lt;&gt;();
        Map&lt;String, Integer&gt; map2 = new HashMap&lt;&gt;();
        Map&lt;String, Integer&gt; unionMap = new HashMap&lt;&gt;();

        float union = 0;
        float intersection = 0;

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i &lt; str1.length() - 1; i++) {
            char c1 = str1.charAt(i);
            char c2 = str1.charAt(i + 1);
            if (Character.isLetter(c1) &amp;&amp; Character.isLetter(c2)) { // 문자일 때
                sb.append(c1);
                sb.append(c2);
                String s = sb.toString().toUpperCase();
                map1.put(s, map1.getOrDefault(s, 0) + 1);
                unionMap.put(s, unionMap.getOrDefault(s, 0) + 1);
                sb.setLength(0);
            }
        }
        for (int i = 0; i &lt; str2.length() - 1; i++) {
            char c1 = str2.charAt(i);
            char c2 = str2.charAt(i + 1);
            if (Character.isLetter(c1) &amp;&amp; Character.isLetter(c2)) { // 문자일 때
                sb.append(c1);
                sb.append(c2);
                String s = sb.toString().toUpperCase();
                map2.put(s, map2.getOrDefault(s, 0) + 1);
                sb.setLength(0);
            }
            else {
                sb.setLength(0);
            }
        }

        for (String key : map2.keySet()) {
            if (unionMap.get(key) != null) { // 해당 값이 이미 존재할 때
                int n = Math.max(unionMap.get(key), map2.get(key));
                unionMap.put(key, n);
            }
            else {
                unionMap.put(key, map2.get(key));
            }
        }

        for (String key : unionMap.keySet()) {
            union += unionMap.get(key);
        }

        for (String key : map1.keySet()) {
            if (map2.containsKey(key)) {
                intersection = intersection + Math.min(map1.get(key), map2.get(key));
            }
        }

        if (union == 0) {
            return 65536;
        }
        return (int)(intersection / union * 65536);
    }
}</code></pre>
<h3 id="ai-코드">AI 코드</h3>
<hr>
<p><strong><em>시간 복잡도: $O(n)$</em></strong>
<strong><em>코드 분석</em></strong></p>
<p>2개의 알파벳 조합으로 가질 수 있는 경우의 수 <code>26*26</code>크기의 배열을 만들어서
해당하는 인덱스 값을 증감시켰음
해당 배열을 통해 <code>intersection</code>과 <code>union</code>값을 얻어 계산</p>
<hr>
<pre><code class="language-java">class Solution {
    private static final int SIZE = 26 * 26;

    public int solution(String str1, String str2) {
        int[] cnt1 = countPairs(str1);
        int[] cnt2 = countPairs(str2);

        int intersection = 0;
        int union = 0;
        for (int i = 0; i &lt; SIZE; i++) {
            intersection += Math.min(cnt1[i], cnt2[i]);
            union        += Math.max(cnt1[i], cnt2[i]);
        }

        if (union == 0) {                 // 두 집합 모두 공집합 → J = 1
            return 65536;
        }
        return intersection * 65536 / union;   // 정수 나눗셈 = 절삭, 오차 없음
    }

    private int[] countPairs(String s) {
        int[] cnt = new int[SIZE];
        for (int i = 0; i &lt; s.length() - 1; i++) {
            char a = s.charAt(i);
            char b = s.charAt(i + 1);
            if (isAlpha(a) &amp;&amp; isAlpha(b)) {
                int idx = (toUpper(a) - &#39;A&#39;) * 26 + (toUpper(b) - &#39;A&#39;);
                cnt[idx]++;
            }
        }
        return cnt;
    }

    private boolean isAlpha(char c) {
        return (c &gt;= &#39;a&#39; &amp;&amp; c &lt;= &#39;z&#39;) || (c &gt;= &#39;A&#39; &amp;&amp; c &lt;= &#39;Z&#39;);
    }

    private char toUpper(char c) {
        return (c &gt;= &#39;a&#39; &amp;&amp; c &lt;= &#39;z&#39;) ? (char) (c - 32) : c;
    }
}</code></pre>
<h2 id="문제-풀이-후기">문제 풀이 후기</h2>
<p>이전부터 느끼는 점이지만 AI는 배열의 활용을 정말 잘 하는 것 같다.
<code>26 * 26</code> 크기의 배열만 하더라도 생각지도 못한 방향이었다.</p>
<p>나의 코드에서 개선점이 꽤나 많이 보여졌다.</p>
<p><strong>첫번째</strong>, <code>float</code>의 사용 대신 <code>intersection</code>에 65536을 먼저 곱한 후
<code>union</code>으로 나누어 리턴했으면 더 안전하게 연산이 가능하다.</p>
<p><strong>둘째</strong>, <code>else sb.setLength(0)</code> 구문이 필요가 없다.
<code>sb.append()</code>는 <code>if</code>문 안에서만 하고 있기 때문이다.</p>
<p><strong>셋째</strong>, <code>unionMap</code>이 필요하지 않다.
<code>sets1.size() + sets2.size() - intersection</code>으로 <code>union</code>을 바로 얻을 수 있다.
<em>수학이 중요한 이유</em></p>
<p><strong>넷째</strong>, <code>isLetter()</code>는 é나 한글의 경우에도 <code>true</code>를 리턴하기 때문에
알파벳 범위를 벗어나게 된다.
따라서 <code>&#39;a&#39;~&#39;z&#39;</code>, <code>&#39;A&#39;~&#39;Z&#39;</code> 범위 검사가 더 적합하다.</p>
<p><strong>다섯째</strong>, <code>unionMap.get(key) != null</code>보다는 위에서 사용한 코드인
<code>containsKey()</code>를 사용하는 것이 더 적합하다.</p>
<p>코드를 작성하면서 값이 제대로 나오지 않아, 리턴값을 <code>intersection</code>, <code>union</code> 만도 사용해보면서 오류 후보를 좁혀나갔다.</p>
<p>해당 방식으로 하나하나 어떤 부분에 오류가 있는지 천천히 탐색하면 
오늘처럼 AI를 사용하지 않고 스스로 문제를 해결할 수 있을 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[튜플_복습]]></title>
            <link>https://velog.io/@hi_soap/%ED%8A%9C%ED%94%8C%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@hi_soap/%ED%8A%9C%ED%94%8C%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Tue, 04 Aug 2026 03:44:40 GMT</pubDate>
            <description><![CDATA[<p><strong>2026.08.04</strong></p>
<h2 id="문제-풀이">문제 풀이</h2>
<h3 id="나의-코드">나의 코드</h3>
<hr>
<p><strong><em>소요 시간: 1시간 8분</em></strong>
<strong><em>시간 복잡도: $O(n^2)$</em></strong></p>
<hr>
<pre><code class="language-java">import java.util.Map;
import java.util.HashMap;

class Solution {
    public int[] solution(String s) {
        Map&lt;Integer, Integer&gt;map = new HashMap&lt;&gt;();

        StringBuilder sb = new StringBuilder();
        sb.append(s.charAt(2));

        for (int i = 3; i &lt; s.length(); i++) {
            char c = s.charAt(i);
            if (c != &#39;{&#39; &amp;&amp; c != &#39;}&#39; &amp;&amp; c != &#39;,&#39;) { // 숫자일 때,
                sb.append(c);
            }
            if (sb.length() &gt; 0 &amp;&amp; (c == &#39;}&#39; || c == &#39;,&#39;)) {
                Integer n = Integer.parseInt(sb.toString());
                map.put(n, map.getOrDefault(n, 0) + 1);
                sb.delete(0, sb.length());
            }
        }
        int[] result = new int[map.size()];
        int idx = 0;
        while(!map.isEmpty()) {
            int maxKey = 0;
            int maxValue = 0;

            for (Integer key : map.keySet()) {
                if (map.get(key) &gt; maxValue) {
                    maxKey = key;
                    maxValue = map.get(key);
                }
            }
            map.remove(maxKey);
            result[idx++] = maxKey;
        }
        return result;
    }
}</code></pre>
<h3 id="ai-코드">AI 코드</h3>
<hr>
<p><strong><em>시간 복잡도: $O(n^2)$</em></strong></p>
<hr>
<p><strong><em>코드 분석</em></strong></p>
<p><code>num * 10 + (c - &#39;0&#39;)</code>을 이용하여 <code>int</code>만을 이용해 숫자 누적</p>
<p><code>merge(num, 1, Integer::sum)</code>은 <code>put(n, getOrDefault(n, 0) + 1)</code>과 동일</p>
<p><code>reading</code>이라는 <code>boolean</code> 변수를 두어 숫자가 저장되어 있는지 판별</p>
<hr>
<pre><code class="language-java">import java.util.HashMap;
import java.util.Map;

class Solution {
    public int[] solution(String s) {
        Map&lt;Integer, Integer&gt; freq = new HashMap&lt;&gt;();

        int num = 0;
        boolean reading = false;
        for (int i = 0; i &lt; s.length(); i++) {
            char c = s.charAt(i);
            if (c &gt;= &#39;0&#39; &amp;&amp; c &lt;= &#39;9&#39;) {
                num = num * 10 + (c - &#39;0&#39;);   // 자릿수 누적
                reading = true;
            } else if (reading) {             // 숫자가 끝나는 지점
                freq.merge(num, 1, Integer::sum);
                num = 0;
                reading = false;
            }
        }

        return freq.entrySet().stream()
                   .sorted((a, b) -&gt; b.getValue() - a.getValue())  // 등장 횟수 내림차순
                   .mapToInt(Map.Entry::getKey)
                   .toArray();
    }
}</code></pre>
<h2 id="문제-풀이-후기">문제 풀이 후기</h2>
<p>간단한 변수 추가로 코드를 훨씬 더 간단하게 만드는 방법을 사용하니
코드가 훨씬 더 깔끔하게 보이고 가독성이 좋아졌다.</p>
<p>마지막에 정렬 하는 부분은 <code>strea()</code>을 이용하여 정렬했는데,
해당 부분이 이해가 잘 안돼서 반복적으로 의식하고 해당 코드를 사용할 수 있을 때 앞으로 사용해야겠다는 생각이 들었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[타겟 넘버_복습]]></title>
            <link>https://velog.io/@hi_soap/%ED%83%80%EA%B2%9F-%EB%84%98%EB%B2%84%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@hi_soap/%ED%83%80%EA%B2%9F-%EB%84%98%EB%B2%84%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Mon, 03 Aug 2026 07:07:47 GMT</pubDate>
            <description><![CDATA[<p><strong>2026.08.03</strong></p>
<h2 id="문제-풀이">문제 풀이</h2>
<h3 id="1차-실행-오류">1차 실행 오류</h3>
<hr>
<p><strong><em>실패 원인 분석</em></strong>
<code>sum + numbers[i]</code>의 과정에서 <code>visited[i] = true</code>후,
<code>sum - numbers[i]</code>의 과정에서 <code>visited[i] == true</code> 이기 때문에
값을 빼는 경우의 dfs가 동작하지 않음</p>
<p>또한 타겟 넘버는 모든 숫자를 다 더하거나 뺐을 경우에만 카운트해야 하는데,
해당 코드의 경우 중간 부분합의 경우도 더함</p>
<hr>
<pre><code class="language-java">class Solution {
    private boolean[] visited;
    private int result = 0;
    public void dfs(int[] numbers, int sum, int target) {
        if (sum == target) {
            result++;
        }
        for (int i = 0; i &lt; numbers.length; i++) {
            if (visited[i]) {
                continue;
            }
            visited[i] = true;
            dfs(numbers, sum + numbers[i], target);
            dfs(numbers, sum - numbers[i], target);
        }
    }
    public int solution(int[] numbers, int target) {
        int len = numbers.length;
        visited = new boolean[len];
        dfs(numbers, 0, target);

        return result;
    }
}</code></pre>
<h3 id="ai-코드">AI 코드</h3>
<pre><code class="language-java">class Solution {
    private int answer = 0;

    private void dfs(int[] numbers, int idx, int sum, int target) {
        if (idx == numbers.length) {
            if (sum == target) {
                answer++;
            }
            return;
        }
        dfs(numbers, idx + 1, sum + numbers[idx], target);
        dfs(numbers, idx + 1, sum - numbers[idx], target);
    }

    public int solution(int[] numbers, int target) {
        dfs(numbers, 0, 0, target);
        return answer;
    }
}</code></pre>
<h2 id="문제-풀이-후기">문제 풀이 후기</h2>
<p>이번 문제는 해결하지 못했다.</p>
<p>처음 공부할 때에도 재귀함수에 대해 큰 어려움이 있었고,
여전히 재귀함수에 대한 어려움이 있다.</p>
<p>나의 코드를 다시 한번 분석해보면,
근본적으로 코드에서 사용한 <code>visited[]</code> 를 사용할 필요가 없었다는 것이다.
위의 실패 원인에서 서술한 것 처럼
처음 <code>visited[i] == true</code>를 한 후, <code>+</code>연산과 <code>-</code>연산을 진행하게 되는데,
재귀적으로 진행하며 <code>-</code> 연산을 진행하지 않는 데에 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[게임 맵 최단 거리_복습]]></title>
            <link>https://velog.io/@hi_soap/%EA%B2%8C%EC%9E%84-%EB%A7%B5-%EC%B5%9C%EB%8B%A8-%EA%B1%B0%EB%A6%AC%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@hi_soap/%EA%B2%8C%EC%9E%84-%EB%A7%B5-%EC%B5%9C%EB%8B%A8-%EA%B1%B0%EB%A6%AC%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Fri, 31 Jul 2026 03:29:38 GMT</pubDate>
            <description><![CDATA[<p><strong>2026.07.31</strong></p>
<h2 id="문제-풀이">문제 풀이</h2>
<h3 id="나의-코드">나의 코드</h3>
<hr>
<p><strong><em>소요 시간: 51분</em></strong>
<strong><em>시간 복잡도: O(N x M)</em></strong></p>
<hr>
<pre><code class="language-java">import java.util.Deque;
import java.util.ArrayDeque;

class Solution {
    private int row;
    private int col;
    private boolean[][] visited;

    public int bfs(int[][] maps) {
        Deque&lt;int[]&gt; queue = new ArrayDeque&lt;&gt;();

        queue.offer(new int[] {0, 0, 1}); // 행, 열, 이동거리

        while(!queue.isEmpty()) {
            int[] cur = queue.poll();

            if (cur[0] == (row - 1) &amp;&amp; cur[1] == (col - 1)) {
                return cur[2];
            }
            int[][] move = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};

            for (int[] m : move) {
                int r = cur[0] + m[0];
                int c = cur[1] + m[1];
                if (r &gt;= row || c &gt;= col || r &lt; 0 || c &lt; 0) {
                    continue;
                }
                else {
                    if (maps[r][c] == 0 || visited[r][c]) {
                        continue;
                    }
                    else {
                        queue.offer(new int[] {r, c, cur[2] + 1});
                        visited[r][c] = true;
                    }
                }
            }
        }
        return -1;
    }

    public int solution(int[][] maps) {
        row = maps.length;
        col = maps[0].length;
        visited = new boolean[row][col];
        int answer = bfs(maps);

        return answer; 
    }     
}</code></pre>
<h3 id="ai-코드">AI 코드</h3>
<hr>
<p><strong><em>시간 복잡도: O(N x M)</em></strong></p>
<hr>
<p><strong><em>코드 분석</em></strong></p>
<p>전체적인 구조는 동일</p>
<hr>
<pre><code class="language-java">import java.util.ArrayDeque;
import java.util.Deque;

class Solution {
    private static final int[] DR = {-1, 1, 0, 0};
    private static final int[] DC = {0, 0, -1, 1};

    public int solution(int[][] maps) {
        int n = maps.length;
        int m = maps[0].length;

        boolean[][] visited = new boolean[n][m];
        Deque&lt;int[]&gt; queue = new ArrayDeque&lt;&gt;();

        queue.offer(new int[] {0, 0, 1});   // 행, 열, 이동 거리
        visited[0][0] = true;               // 시작점 방문 처리

        while (!queue.isEmpty()) {
            int[] cur = queue.poll();
            int r = cur[0], c = cur[1], dist = cur[2];

            if (r == n - 1 &amp;&amp; c == m - 1) {
                return dist;
            }

            for (int d = 0; d &lt; 4; d++) {
                int nr = r + DR[d];
                int nc = c + DC[d];

                if (nr &lt; 0 || nr &gt;= n || nc &lt; 0 || nc &gt;= m) continue;
                if (maps[nr][nc] == 0 || visited[nr][nc]) continue;

                visited[nr][nc] = true;     // 큐에 넣는 시점에 방문 처리 (중복 삽입 방지)
                queue.offer(new int[] {nr, nc, dist + 1});
            }
        }
        return -1;
    }
}</code></pre>
<h2 id="문제-풀이-후기">문제 풀이 후기</h2>
<p>나의 코드에 존재하는 3가지 문제 및 개선점이 존재함</p>
<ul>
<li><p>기존 나의 코드에서 시작 위치인 <code>visited[0][0] = true</code>를 하지 않아
<code>(0, 0)</code>이 거리 3으로 다시 큐에 들어가는 오류가 발생</p>
<p>시작 지점의 미방문 처리는 BFS에서 가장 흔한 감점/오답 포인트임</p>
</li>
<li><p><code>move</code> 배열을 <code>while</code> 루프 안에서 매번 재생성 하고 있음</p>
</li>
<li><p><code>else</code> 중첩 + <code>continue</code>가 섞여 있어 depth가 깊음</p>
</li>
</ul>
<p>BFS는 DFS에 비해 상대적으로 문제 유형이 자주 출제되지 않았기에 
해당 자료구조에 대해 사용했던 적이 적었다.</p>
<p>이 문제는 이전에 DFS로 해결을 시도했다가 실패했던 문제인데
이번에는 BFS로 한 번에 해결하고
익숙하지 않았던 BFS에 대해 다시 한번 복습할 수 있어서 좋았다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[롤케이크 자르기_복습]]></title>
            <link>https://velog.io/@hi_soap/%EB%A1%A4%EC%BC%80%EC%9D%B4%ED%81%AC-%EC%9E%90%EB%A5%B4%EA%B8%B0%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@hi_soap/%EB%A1%A4%EC%BC%80%EC%9D%B4%ED%81%AC-%EC%9E%90%EB%A5%B4%EA%B8%B0%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Wed, 29 Jul 2026 03:07:55 GMT</pubDate>
            <description><![CDATA[<p><strong>2026.07.29</strong></p>
<h2 id="문제-풀이">문제 풀이</h2>
<h3 id="나의-코드">나의 코드</h3>
<hr>
<p><strong><em>소요 시간: 19분</em></strong>
<strong><em>시간 복잡도: $O(n)$</em></strong></p>
<hr>
<p><strong><em>개선점</em></strong></p>
<pre><code class="language-java">Integer t = topping[i];</code></pre>
<p>의 과정에서 오토 언박싱이 지속적으로 발생함
<code>int</code>로 선언 후, <code>put</code> 시점에만 박싱되게 하는 것이 나음</p>
<hr>
<pre><code class="language-java">import java.util.Map;
import java.util.HashMap;

class Solution {
    public int solution(int[] topping) {
        int result = 0;
        Map&lt;Integer, Integer&gt; right = new HashMap&lt;&gt;();
        Map&lt;Integer, Integer&gt; left = new HashMap&lt;&gt;();

        for (int i = 0; i &lt; topping.length; i++) {
            Integer t = topping[i];
            right.put(t, right.getOrDefault(t, 0) + 1);
        }
        for (int i = 0; i &lt; topping.length; i++) {
            Integer t = topping[i];
            left.put(t, left.getOrDefault(t, 0) + 1);
            right.put(t, right.get(t) - 1);
            if (right.get(t) &lt;= 0) {
                right.remove(t);
            }
            if (left.size() == right.size()) {
                result++;
            }
        }
        return result;
    }
}</code></pre>
<h3 id="ai-코드">AI 코드</h3>
<hr>
<p><strong><em>시간 복잡도: $O(n)$</em></strong></p>
<hr>
<p><strong><em>코드 분석</em></strong></p>
<p><code>right</code>는 개수가 계속 빠지므로 <code>rightCnt</code>를 사용하고,</p>
<p><code>left</code>는 개수가 빠지지 않으므로, 
<code>leftHas</code>를 이용하여 이미 가지고 있던 토핑인지 구분한다.</p>
<hr>
<pre><code class="language-java">class Solution {
    public int solution(int[] topping) {
        int[] rightCnt = new int[10001];
        boolean[] leftHas = new boolean[10001];
        int leftKind = 0, rightKind = 0, answer = 0;

        for (int t : topping) {
            if (rightCnt[t]++ == 0) rightKind++;
        }

        // i번째까지 철수, 나머지 동생 → 마지막 인덱스는 자를 수 없으므로 제외
        for (int i = 0; i &lt; topping.length - 1; i++) {
            int t = topping[i];
            if (--rightCnt[t] == 0) rightKind--;
            if (!leftHas[t]) {
                leftHas[t] = true;
                leftKind++;
            }
            if (leftKind == rightKind) answer++;
        }
        return answer;
    }
}</code></pre>
<h2 id="문제-풀이-후기">문제 풀이 후기</h2>
<p>배열의 길이가 <code>1,000,000</code> 이하인 조건을 보고, 2중 반복문을 사용하면 안된다는 것을 이전의 문제를 풀면서 알아냈다.</p>
<p>이전에는 고려하지 않고 일단 코드 작성 뒤 시간 초과 오류가 났을 부분이지만,
이전과는 달리 한 번에 통과하여 발전하고 있는 자신이 보기 좋다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로세스_복습]]></title>
            <link>https://velog.io/@hi_soap/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@hi_soap/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Tue, 28 Jul 2026 02:56:53 GMT</pubDate>
            <description><![CDATA[<p><strong>2026.07.28</strong></p>
<h2 id="문제-풀이">문제 풀이</h2>
<h3 id="나의-코드">나의 코드</h3>
<hr>
<p><strong><em>소요 시간: 37분</em></strong>
<strong><em>시간 복잡도: $O(n^3)$</em></strong></p>
<hr>
<pre><code class="language-java">import java.util.Arrays;

class Solution {
    public int solution(int[] priorities, int location) {
        int maxIdx = 0;
        int len = priorities.length;
        for (int i = 1; i &lt; len; i++) {
            if (priorities[maxIdx] &lt; priorities[i]) {
                maxIdx = i;
            }
        }
        int order = 1;
        int idx = maxIdx;
        while(true) {
            while(true) {
                int p = priorities[idx];
                boolean isExist = Arrays.stream(priorities).anyMatch(a -&gt; a &gt; p);
                if (!isExist) {
                    priorities[idx] = -1;
                    break;
                }
                idx = (idx + 1) % len;
            }
            if (idx == location) {
                break;
            }
            idx = (idx + 1) % len;
            order++;
        }
        return order;
    }
}</code></pre>
<h3 id="ai-코드">AI 코드</h3>
<hr>
<p><strong><em>시간 복잡도: $O(n^2)$</em></strong></p>
<hr>
<p><strong><em>코드 분석</em></strong></p>
<p><strong>인덱스</strong>와 <strong>우선순위</strong>의 분리
인덱스는 <code>queue</code>, 우선순위는 <code>sorted[]</code>로 각각 분리하여 관리</p>
<p><strong>우선순위</strong>의 경우 <code>.sort()</code>를 이용해 오름차순으로 정렬 후,
<code>top</code>값을 이용한 가장 후방의 인덱스부터 시작하여 내림차순처럼 사용함</p>
<p><strong>인덱스</strong>의 경우 계속해서 순환하는 흐름을 만들어냄
0부터 시작하여 해당 인덱스에 해당하는 값이 
<code>soted[top]</code>의 값과 동일한 경우, 현재 가장 높은 우선순위를 갖는 값이 된다.</p>
<p>두 값이 일치되면 <code>top--</code>를 하여 
<code>location</code>과 일치할 때 까지 반복해서 진행한다.</p>
<hr>
<pre><code class="language-java">import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;

class Solution {
    public int solution(int[] priorities, int location) {
        int n = priorities.length;

        // 오름차순 정렬 후 뒤에서부터 꺼내면 = 남은 문서 중 최대 우선순위
        int[] sorted = priorities.clone();
        Arrays.sort(sorted);
        int top = n - 1;

        // 원래 인덱스를 큐에 담아 대기열 순서 유지
        Deque&lt;Integer&gt; queue = new ArrayDeque&lt;&gt;();
        for (int i = 0; i &lt; n; i++) {
            queue.offer(i);
        }

        int order = 0;
        while (!queue.isEmpty()) {
            int cur = queue.poll();
            if (priorities[cur] == sorted[top]) {   // 최우선순위 → 인쇄
                top--;
                order++;
                if (cur == location) {
                    return order;
                }
            } else {                                // 뒤로 밀기
                queue.offer(cur);
            }
        }
        return order;
    }
}</code></pre>
<h2 id="문제-풀이-후기">문제 풀이 후기</h2>
<p>나의 코드에서 <code>anyMatch()</code>를 사용하여 
해당 값보다 더 큰 값이 있는지 탐색을 했기 때문에 
<code>maxIdx</code>를 탐색하여 사용할 필요가 없었다.</p>
<p>이와 같이 코드의 개선점이 뚜렷하게 보였다.</p>
<p>두 번째로 AI 코드를 보며 든 생각이 있다.
예전부터 수학 시험을 보면, 
기본 문제나 문제집에서 이미 풀어봤던 문제는 잘 풀었지만,
응용 문제의 경우에는 처음부터 막혀서 항상 풀지 못했다.</p>
<p>코딩도 마찬가지로 기본적인 사용은 쉽게 가능하지만,
위의 AI 코드와 같이 응용을 해서 사용한다는 발상 자체가 떠오르지 않는다.</p>
<p>문제집에서 풀어 봤던 문제는 잘 푸는 것 처럼
이와 같은 응용된 코드를 많이 보면서
부족한 코드의 응용을 하는 방법에 익숙해지는 수 밖에 없다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[전화번호 목록_복습]]></title>
            <link>https://velog.io/@hi_soap/%EC%A0%84%ED%99%94%EB%B2%88%ED%98%B8-%EB%AA%A9%EB%A1%9D%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@hi_soap/%EC%A0%84%ED%99%94%EB%B2%88%ED%98%B8-%EB%AA%A9%EB%A1%9D%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Sun, 26 Jul 2026 05:16:16 GMT</pubDate>
            <description><![CDATA[<p><strong>2026.07.26</strong></p>
<h2 id="문제-풀이">문제 풀이</h2>
<h3 id="1차-실행-오류">1차 실행 오류</h3>
<hr>
<p><code>79.2/100</code></p>
<p>실패 및 시간 초과</p>
<hr>
<p><strong><em>실패 원인 분석</em></strong></p>
<p><code>123</code>, <code>12</code> 순서의 배열에서
<code>12</code>는 <code>123</code>으로 시작하지 않지만, <code>123</code>은 <code>12</code>로 시작하는 경우를 고려하지 않음</p>
<hr>
<pre><code class="language-java">class Solution {
    public boolean solution(String[] phone_book) {
        for (int i = 0; i &lt; phone_book.length; i++) {
            for (int j = i + 1; j &lt; phone_book.length; j++) {
                if (phone_book[j].startsWith(phone_book[i])) {
                    return false;
                }
            }
        }
        return true;
    }
}</code></pre>
<h3 id="2차-실행-오류">2차 실행 오류</h3>
<hr>
<p><code>91.7/100</code></p>
<p>시간 초과</p>
<hr>
<p><strong><em>시간 초과 원인 분석</em></strong></p>
<p><code>1 &lt;= phone_book &lt;= 1,000,000</code> 이므로 2중 <code>for</code>문을 사용하면 안됨</p>
<hr>
<pre><code class="language-java">class Solution {
    public boolean solution(String[] phone_book) {
        if (phone_book.length &lt;= 1) {
            return true;
        }

        for (int i = 0; i &lt; phone_book.length; i++) {
            for (int j = 0; j &lt; phone_book.length; j++) {
                if (i == j) {
                    continue;
                }
                if (phone_book[j].startsWith(phone_book[i])) {
                    return false;
                }
            }
        }
        return true;
    }
}</code></pre>
<h3 id="나의-코드">나의 코드</h3>
<hr>
<p><strong><em>소요 시간: 31분</em></strong>
<strong><em>시간 복잡도: $O(n log n)$</em></strong></p>
<hr>
<pre><code class="language-java">import java.util.Arrays;

class Solution {
    public boolean solution(String[] phone_book) {
        Arrays.sort(phone_book);

        if (phone_book.length &lt;= 1) {
            return true;
        }

        for (int i = 1; i &lt; phone_book.length; i++) {
            if (phone_book[i].startsWith(phone_book[i - 1]) || 
                phone_book[i - 1].startsWith(phone_book[i])) {
                return false;
            }
        }
        return true;
    }
}</code></pre>
<h3 id="ai-코드">AI 코드</h3>
<hr>
<p><strong><em>시간 복잡도: $O(n)$</em></strong></p>
<hr>
<p><strong><em>코드 분석</em></strong></p>
<p><code>HashSet</code>의 <code>.contains()</code>의 조회 속도가 $O(1)$이라는 점을 이용하여 해결</p>
<hr>
<pre><code class="language-java">import java.util.HashSet;

class Solution {
    public boolean solution(String[] phone_book) {
        HashSet&lt;String&gt; set = new HashSet&lt;&gt;();
        for (String number : phone_book) {
            set.add(number);
        }

        for (String number : phone_book) {
            for (int i = 1; i &lt; number.length(); i++) {
                if (set.contains(number.substring(0, i))) {
                    return false;
                }
            }
        }
        return true;
    }
}</code></pre>
<h2 id="문제-풀이-후기">문제 풀이 후기</h2>
<p><code>substring()</code>과 <code>contains()</code>의 혼합 사용은 생각하지 못했다.
<code>Hash</code>의 활용 방법은 무궁무진 하다는 생각이 들었다.</p>
<p>이전에 해결하지 못했던 시간 초과 오류를 AI를 활용하지 않고
스스로 원인 분석 및 해결했다는 점에서 높은 점수를 주고 싶다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[캐시_복습]]></title>
            <link>https://velog.io/@hi_soap/%EC%BA%90%EC%8B%9C-5b2um496</link>
            <guid>https://velog.io/@hi_soap/%EC%BA%90%EC%8B%9C-5b2um496</guid>
            <pubDate>Thu, 23 Jul 2026 03:11:28 GMT</pubDate>
            <description><![CDATA[<p><strong>2026.07.23</strong></p>
<h2 id="문제-풀이">문제 풀이</h2>
<h3 id="1차-실행-오류">1차 실행 오류</h3>
<hr>
<p><code>90/100</code></p>
<p>실패</p>
<hr>
<p><strong><em>실패 원인 분석</em></strong></p>
<p><code>cacheSize == 0</code>일 때,
캐시에 하나의 데이터가 저장이 되는 경우의 수를 고려하지 않음</p>
<hr>
<pre><code class="language-java">import java.util.Map;
import java.util.HashMap;

class Solution {
    public int solution(int cacheSize, String[] cities) {
        int runTime = 0;
        Map&lt;String, Integer&gt; map = new HashMap&lt;&gt;();

        for (int i = 0; i &lt; cities.length; i++) {
            for (String key : map.keySet()) { // 캐시 갱신
                map.put(key, map.get(key) + 1);
            }

            String city = cities[i].toUpperCase();
            if (map.get(city) == null) { // cache miss 일 때
                runTime += 5;
                if (map.size() &gt;= cacheSize) { // cache가 다 찼을 때
                    String removeCity = &quot;s&quot;;
                    int min = 0;
                    for (String key : map.keySet()) {
                        if (map.get(key) &gt; min) {
                            removeCity = key;
                            min = map.get(key);
                        }
                    }
                    map.remove(removeCity); // 가장 오래 전에 사용한 캐시 삭제
                }
                map.put(city, 0); // 새로운 캐시 삽입
            }
            else {
                runTime++;
                map.put(city, 0); // 사용한 캐시 초기화
            }
        }
        return runTime;
    }
}</code></pre>
<h3 id="나의-코드">나의 코드</h3>
<hr>
<p><strong><em>소요 시간: 23분</em></strong>
<strong><em>시간 복잡도: $O(n)$</em></strong></p>
<hr>
<pre><code class="language-java">import java.util.Map;
import java.util.HashMap;

class Solution {
    public int solution(int cacheSize, String[] cities) {
        if (cacheSize == 0) {
            return 5 * cities.length;
        }
        int runTime = 0;
        Map&lt;String, Integer&gt; map = new HashMap&lt;&gt;();

        for (int i = 0; i &lt; cities.length; i++) {
            for (String key : map.keySet()) { // 캐시 갱신
                map.put(key, map.get(key) + 1);
            }

            String city = cities[i].toUpperCase();
            if (map.get(city) == null) { // cache miss 일 때
                runTime += 5;
                if (map.size() &gt;= cacheSize) { // cache가 다 찼을 때
                    String removeCity = &quot;s&quot;;
                    int min = 0;
                    for (String key : map.keySet()) {
                        if (map.get(key) &gt; min) {
                            removeCity = key;
                            min = map.get(key);
                        }
                    }
                    map.remove(removeCity); // 가장 오래 전에 사용한 캐시 삭제
                }
                map.put(city, 0); // 새로운 캐시 삽입
            }
            else {
                runTime++;
                map.put(city, 0); // 사용한 캐시 초기화
            }
        }
        return runTime;
    }
}</code></pre>
<h3 id="ai-코드">AI 코드</h3>
<hr>
<p><strong><em>시간 복잡도: $O(n)$</em></strong></p>
<hr>
<p><strong><em>코드 분석</em></strong></p>
<p><code>LinkedList</code>를 사용하여 순서를 유지한 채 해시를 유지
캐시가 사용되면 기존 캐시를 뺀 후 재삽입</p>
<hr>
<pre><code class="language-java">import java.util.LinkedList;

class Solution {
    public int solution(int cacheSize, String[] cities) {
        if (cacheSize == 0) return 5 * cities.length;

        int runTime = 0;
        LinkedList&lt;String&gt; cache = new LinkedList&lt;&gt;();

        for (String city : cities) {
            String upper = city.toUpperCase();
            if (cache.remove(upper)) {   // hit: 기존 원소 제거 후 뒤에 재삽입
                runTime += 1;
            } else {                     // miss
                runTime += 5;
                if (cache.size() &gt;= cacheSize) {
                    cache.pollFirst();   // 가장 오래된 것 제거 (LRU)
                }
            }
            cache.addLast(upper);        // 최근 사용으로 갱신
        }
        return runTime;
    }
}</code></pre>
<h2 id="문제-해결-후기">문제 해결 후기</h2>
<p>익숙하지 않았던 해시 사용을 점점 능숙하게 사용하고 있다는 생각이 든다.
동시에 <code>LinkedList</code>와 같은 다양한 해시들도 고루고루 활용해가며
적재적소에 활용하는 능력을 키워야겠다고 생각했다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[피로도_복습]]></title>
            <link>https://velog.io/@hi_soap/%ED%94%BC%EB%A1%9C%EB%8F%84%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@hi_soap/%ED%94%BC%EB%A1%9C%EB%8F%84%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Wed, 22 Jul 2026 02:40:19 GMT</pubDate>
            <description><![CDATA[<p><strong>2026.07.22</strong></p>
<h2 id="문제-풀이">문제 풀이</h2>
<h3 id="나의-코드">나의 코드</h3>
<hr>
<p><strong><em>소요 시간: 20분</em></strong>
<strong><em>시간 복잡도: $O(n!) (n = 던전 개수)$</em></strong></p>
<hr>
<pre><code class="language-java">class Solution {
    boolean[] visited;
    int result = 0;
    public void dfs(int k, int[][] dungeons, int cnt) {
        result = Math.max(result, cnt);
        for (int i = 0; i &lt; dungeons.length; i++) {
            if (visited[i] || dungeons[i][0] &gt; k) {
                continue;
            }
            visited[i] = true;
            dfs(k - dungeons[i][1], dungeons, cnt + 1);
            visited[i] = false;
        }
    }

    public int solution(int k, int[][] dungeons) {
        visited = new boolean[dungeons.length];
        dfs(k, dungeons, result);

        return result;
    }
}</code></pre>
<h3 id="ai-코드">AI 코드</h3>
<hr>
<p><strong><em>시간 복잡도: $O(n!) (n = 던전 개수)$</em></strong></p>
<hr>
<p><strong><em>코드 분석</em></strong></p>
<p>전체적인 코드 구조는 거의 동일하고 가독성 측면에서 일부 변경되었음.</p>
<hr>
<pre><code class="language-java">class Solution {
    static int answer = 0;
    static boolean[] visited;

    public int solution(int k, int[][] dungeons) {
        visited = new boolean[dungeons.length];
        dfs(k, 0, dungeons);
        return answer;
    }

    private void dfs(int k, int depth, int[][] dungeons) {
        answer = Math.max(answer, depth);
        for (int i = 0; i &lt; dungeons.length; i++) {
            if (!visited[i] &amp;&amp; k &gt;= dungeons[i][0]) {
                visited[i] = true;
                dfs(k - dungeons[i][1], depth + 1, dungeons);
                visited[i] = false;
            }
        }
    }
}</code></pre>
<h2 id="문제-풀이-후기">문제 풀이 후기</h2>
<p>이 문제를 처음 풀었을 때에는 dfs에 대한 활용이 많이 부족했다.</p>
<p>복습을 하면서 아주 쉽게 문제를 해결했는데 
이전보다 실력이 나아진 것은 분명하나, 
문제 해결 방법을 외워서 푼 것 같아 
다른 문제들도 계속 풀어보며 점점 고난이도의 문제들을 해결하는 것이 
필요할 것 같다.</p>
<p>틀렸던 문제들에 대해 복습을 반복하며 내가 어떤 점이 부족했고 보완해야 하는가를 깨닫고, 정답률이 낮은 고난이도 문제들과 더불어
Level 3의 문제들을 도전해가는 방향으로 진행하면 실력 향상이 이루어질 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[H-Index_복습]]></title>
            <link>https://velog.io/@hi_soap/H-Index%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@hi_soap/H-Index%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Tue, 21 Jul 2026 01:39:20 GMT</pubDate>
            <description><![CDATA[<p><strong>2026.07.21</strong></p>
<h2 id="문제-풀이">문제 풀이</h2>
<h3 id="1차-실행-오류">1차 실행 오류</h3>
<hr>
<p><code>6.3/100</code></p>
<p>실패</p>
<hr>
<p><strong><em>실패 원인 분석</em></strong></p>
<pre><code class="language-java">[7, 0, 3]의 배열이 입력으로 주어지는 경우,
정답이 2가 되어야 하지만, 1이 출력되는데, 그 이유는

for (int i = 0; i &lt; citations.length; i++) {
    for (Integer key : map.keySet()) {
        if (key &lt; citations[i]) {
            map.put(key, map.get(key) + 1);
        }
    }
map.put(citations[i], map.getOrDefault(citations[i], 0) + 1);
}

에서 큰 인용 횟수가 먼저 들어오면, 작은 횟수는 증가하지 않기 때문임

따라서 오름차순으로 정렬해서 해결할 수 있음</code></pre>
<hr>
<pre><code class="language-java">import java.util.Map;
import java.util.HashMap;

class Solution {
    public int solution(int[] citations) {
        Map&lt;Integer, Integer&gt; map = new HashMap&lt;&gt;();

        for (int i = 0; i &lt; citations.length; i++) {
            for (Integer key : map.keySet()) {
                if (key &lt; citations[i]) {
                    map.put(key, map.get(key) + 1);
                }
            }
            map.put(citations[i], map.getOrDefault(citations[i], 0) + 1);
        }
        int h = 0;
        for (Integer key : map.keySet()) {
            int n = Math.min(key, map.get(key));
            h = (h &lt;= n ? n : h);
        }

        return h;
    }
}</code></pre>
<h3 id="나의-코드">나의 코드</h3>
<hr>
<p><strong><em>소요 시간: 30분</em></strong>
<strong><em>시간 복잡도: $O(n^2)$</em></strong></p>
<hr>
<pre><code class="language-java">import java.util.Map;
import java.util.HashMap;
import java.util.Arrays;

class Solution {
    public int solution(int[] citations) {
        Arrays.sort(citations);
        Map&lt;Integer, Integer&gt; map = new HashMap&lt;&gt;();

        for (int i = 0; i &lt; citations.length; i++) {
            for (Integer key : map.keySet()) {
                if (key &lt; citations[i]) {
                    map.put(key, map.get(key) + 1);
                }
            }
            map.put(citations[i], map.getOrDefault(citations[i], 0) + 1);
        }
        int h = 0;
        for (Integer key : map.keySet()) {
            int n = Math.min(key, map.get(key));
            h = (h &lt;= n ? n : h);
        }

        return h;
    }
}</code></pre>
<h3 id="ai-코드">AI 코드</h3>
<hr>
<p><strong><em>시간 복잡도: $O(n log n)$</em></strong></p>
<hr>
<p><strong><em>코드 해석</em></strong></p>
<pre><code class="language-java">입력된 배열을 오름차순으로 정렬했기 때문에
cirtations[i]의 현재 인덱스로부터 총 길이까지는 차는
현재 상황에서 인용 가능한 최대 논문 수가 됨

따라서 현재 인용한 논문 횟수가 이보다 더 크다면 해당 값이 최댓값이 되는 구조</code></pre>
<hr>
<pre><code class="language-java">class Solution {
    public int solution(int[] citations) {
        Arrays.sort(citations);
        int n = citations.length;
        for (int i = 0; i &lt; n; i++) {
            int h = n - i;               // i번째 이후 논문 수
            if (citations[i] &gt;= h) return h;
        }
        return 0;
    }
}</code></pre>
<h2 id="문제-풀이-후기">문제 풀이 후기</h2>
<p>이전 문제를 풀면서도 느꼈던 점이지만, 이번 AI 코드를 보며 더욱 더
수학적 사고방식이 정말 중요하다고 느낀다.</p>
<p>해당 사고방식이 있다면 같은 문제라도 코드가 훨씬 더 간결해진다.
결론적으로 문제를 많이 풀며 모범 답안을 많이 접하는 것 밖에는 정답이 없다.</p>
]]></description>
        </item>
    </channel>
</rss>