<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>이면지</title>
    <link>https://programming-story.tistory.com/</link>
    <description>프로그래밍 일기</description>
    <language>ko</language>
    <pubDate>Tue, 11 Aug 2026 02:08:56 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>한 면만 쓴 종이</managingEditor>
    <image>
      <title>이면지</title>
      <url>https://tistory1.daumcdn.net/tistory/4921752/attach/01d3064ffd834f3a9b8876b81b496bab</url>
      <link>https://programming-story.tistory.com</link>
    </image>
    <item>
      <title>큐시즘 31기를 끝마치며</title>
      <link>https://programming-story.tistory.com/209</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;큐시즘 지원 계기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학교를 졸업 유예하고 계속 입사 지원서를 제출하고 코테 등 공부를 하며 지냈습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매일매일 아침부터 도서관에서 공부하다 보니 사람 만날 일도 줄어들고 하루 종일 고독하더라고요.. (고독정식 9만 개)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 동아리 활동이라도 하면서 사람을 좀 만나자는 생각을 했습니다. 그리고 가지고 있던 프로젝트들이 좀 오래되기도 했고요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마침 큐시즘이 모집 중이길래 하루 만에 후다닥 써서 제출했습니다. 기존에 자소서를 써왔던 게 있어서 그래도 수월하게 작성했던 것 같아요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;큐시즘 들어가기&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;지원서&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 백엔드 파트로 지원했습니다. 저는 주로 START 기법을 이용해서 자소서를 작성합니다. STAR 기법이 가장 유명한데, 저 같은 글 모지리에게는.. 자세하게 하나하나 무엇을 써야 하는지 정해져 있는 게 작성하기 쉽다고 느껴져서 해당 기법을 주로 사용하게 됐습니다. 어느 동아리던 회사던 지원하시려는 분들은 참고하셔도 좋을 것 같아요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;면접&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;면접은 기본 CS 지식을 주되게 준비해 갔어요. 근데 질문은 제 프로젝트 위주로 나왔답니다. 게다가 포트폴리오에만 있는 내용 기반 질문도 있어서 약간 당황하기도 했던 기억이 있어요. 그래도 본인이 직접 한 경험이라면 아예 대답을 못할 질문들은 없었던 것 같아요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 저는 당황해서 조금 틀리게 답했던 것두 있었어요 ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기업프로젝트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;밀크걸즈&lt;/b&gt;라는 팀과 기업 프로젝트를 진행했어요. 서울우유 기업 과제였는데 정말 정말 좋은 경험이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람들도 좋았고 결과물도 좋았어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기간이 짧다 보니 밤을 정말.. 정말 많이 새웠어요. 그래도 그만큼 보람찼습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간략히 프로젝트를 소개해보자면, 지능형 세금계산서 검증 시스템입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람이 일일이 홈택스에서 세금계산서를 검증하는 과정을 최대한 단축하는 것이 백엔드의 핵심이었어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제 생각에는 백엔드의 역할이 중요한 프로젝트였던 것 같아요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;홈택스에서 직접 세금계산서를 검증하는 과정을 단축한 방법은 CODEF API를 사용하는 것이었어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 API를 사용하는 과정에서 많은 시행착오를 겪었습니다. 우선, 본인인증 과정이 필요했는데, 이것 때문에 API 연동 방식이 많이 복잡했어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 포스트에 기술적인 부분을 크게 담지는 않을 생각이라 자세한 설명은 생략하겠습니다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여튼 해당 API를 연결하면서 한 단계 성장한 것 같아요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 같은 파트 팀원도 함께 열심히 해주어서 같이 으쌰으쌰 하는 분위기가 조성됐어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 파트들도 정말 열심히 하는 게 느껴져서 더 애정이 갔답니다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;밋업프로젝트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건.. 팀명을 밝히지 않을게요 ㅎㅎ 조금 부끄러워서..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;밋업 프로젝트로는 공모전에도 나가게 되었어요. 아직 결과가 나오지 않았는데 좋은 결과가 있었으면 좋겠네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;밋업 프로젝트 사람들도 좋았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 프로젝트는 기업 프로젝트보다는 백엔드의 중요도가 적었어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 Spring AI를 사용해 본 것에 만족하고 있답니다. 여러분도 Spring AI 사용해 보세요. 이전처럼 DTO 무덤을 만들지 않아도 되고, 응답도 제시한 DTO에 담아서 줘서 정말 편해요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아쉬웠던 점은 마지막 UT와 밋업데이를 가지 못했다는 거예요 ㅠㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 찐막인 큐시즘의 밤은 참석하기 때문에 그날 잘 즐기겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지나 보니 짧았던 큐시즘 활동을 이렇게 잘 끝마치게 되어 뿌듯하네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 기억 많이 쌓고 갑니다~&lt;/p&gt;</description>
      <category>백엔드</category>
      <category>큐시즘</category>
      <author>한 면만 쓴 종이</author>
      <guid isPermaLink="true">https://programming-story.tistory.com/209</guid>
      <comments>https://programming-story.tistory.com/209#entry209comment</comments>
      <pubDate>Fri, 6 Jun 2025 01:03:34 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 징검다리 건너기 (자바)</title>
      <link>https://programming-story.tistory.com/204</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/64062&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/64062&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1743168785811&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그래머스&quot; data-og-description=&quot;SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/64062&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bFhRbB/hyYvf5YmL6/PHgbhgkIRD9XDPKm9CBQSk/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960,https://scrap.kakaocdn.net/dn/bv55Ko/hyYvrefK6i/DCUPSJLijTKJmgRrEOmKoK/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/64062&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/64062&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bFhRbB/hyYvf5YmL6/PHgbhgkIRD9XDPKm9CBQSk/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960,https://scrap.kakaocdn.net/dn/bv55Ko/hyYvrefK6i/DCUPSJLijTKJmgRrEOmKoK/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 조건 때문에 완전탐색은 불가능하다고 판단했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #263747; text-align: left;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;stones 배열의 크기는 1 이상 200,000 이하입니다.&lt;/li&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;stones 배열 각 원소들의 값은 1 이상 200,000,000 이하인 자연수입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 DP 나 이분탐색을 사용해야 겠다고 생각했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- DP: DP를 적용해도 시간 복잡도 단축이 크지 않을 것 같았다. 최악의 경우 stones의 원소 값만큼 시간복잡도가 깊어질 수 있기 때문에..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이분탐색: 위의 이유로 이분탐색을 적용해야 겠다는 삘이 왔다.. 하지만 어떻게 적용해야 할지 감을 못 잡았다. 그래서 다른 분들 풀이를 참고했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;left와 right를 사람 수의 min과 max로 잡으면 풀이가 가능했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1743168914599&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Solution {
    static int[] stones;
    static int k;
    
    public int solution(int[] stones, int k) {
        this.stones = stones;
        this.k = k;
        
        int answer = 0;
        int min = 1; 
        int max = 200000000;
	      
        while (min &amp;lt;= max) {
            int mid = (min + max) / 2;
            
            if (isPossible(mid)) {
                min = mid + 1;
                answer = Math.max(answer, mid);
            } else {
                max = mid - 1;
            }
        }
        
        return answer;
    }
    
    boolean isPossible(int friends) {
      	int skip = 0;
        
        for (int stone : stones) {
            if (stone - friends &amp;lt; 0) {
                skip++;
            }
            else {
                skip = 0;
            }
            
            if (skip == k) {
                return false;
            }
        }
        
        return true;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;left와 right는 거리 또는 위치를 기준으로 잡아야 한다는 생각이 있었던 것 같다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[느낀점]&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이분탐색을 할 때 left, right, mid는 꼭 거리나 위치가 아니어도 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간복잡도를 올리는 원인이 되는 값을 left, right, mid로 잡는 경우도 고려하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(이 문제에서는 사람 수를 left, right, mid로 잡았다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>코딩 테스트</category>
      <category>이분탐색</category>
      <category>자바</category>
      <category>징검다리 건너기</category>
      <author>한 면만 쓴 종이</author>
      <guid isPermaLink="true">https://programming-story.tistory.com/204</guid>
      <comments>https://programming-story.tistory.com/204#entry204comment</comments>
      <pubDate>Fri, 28 Mar 2025 22:44:15 +0900</pubDate>
    </item>
    <item>
      <title>[백준] 1806번 부분합 자바(Java)</title>
      <link>https://programming-story.tistory.com/203</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1806&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1806&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전형적인 투포인터 문제다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;투포이터는 O(N)의 시간복잡도를 갖는다. 시간제한이 0.5초인 이 문제에 사용하기 딱이다. &lt;i&gt;&lt;s&gt;(사실 자바는 1초 제한.. ㅠ)&lt;/s&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1742891314963&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int N = Integer.parseInt(st.nextToken());
        int S = Integer.parseInt(st.nextToken());
        int[] arr = new int[N + 1];
        st = new StringTokenizer(br.readLine());
        for (int i = 0; i &amp;lt; N; i++) {
            arr[i] = Integer.parseInt(st.nextToken());
        }

        int left = 0;
        int right = 0;
        int sum = 0;
        int ans = Integer.MAX_VALUE;

        while (right &amp;lt;= N &amp;amp;&amp;amp; left &amp;gt;= 0) {
            if (sum &amp;gt;= S) {
                ans = Math.min(ans, right - left);
                sum -= arr[left++];
            } else {
                sum += arr[right++];
            }
        }
        
        if (ans == Integer.MAX_VALUE) {
            ans = 0;
        }
        System.out.println(ans);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[기억하자]&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;투 포인터&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- O(n) 의 시간복잡도를 가진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;구간합&lt;/b&gt;, &lt;b&gt;부분합&lt;/b&gt; 연산에 사용하기 적합하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이름이 비슷한(?) 이분탐색과는 차이가 크다. &lt;b&gt;투 포인터&lt;/b&gt;는 보통 연속된 구간의 특성을 활용하여 조건을 만족하는 구간을 찾고, &lt;b&gt;이분탐색&lt;/b&gt;은 특정 값을 찾기 위해 많이 사용되는 알고리즘이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>코딩 테스트</category>
      <category>1806</category>
      <category>백준</category>
      <category>자바</category>
      <author>한 면만 쓴 종이</author>
      <guid isPermaLink="true">https://programming-story.tistory.com/203</guid>
      <comments>https://programming-story.tistory.com/203#entry203comment</comments>
      <pubDate>Tue, 25 Mar 2025 17:33:14 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 이모티콘 할인행사</title>
      <link>https://programming-story.tistory.com/202</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/150368&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/150368&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쌩구현 문제였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[풀이한 코드]&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1742819625577&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

class Solution {
        static final Map&amp;lt;Integer, Integer&amp;gt; percentMap = Map.of(10, 9, 20, 8, 30, 7, 40, 6);
    static final int[] pers = new int[]{10, 20, 30, 40};
    
    static int[][] users;
    static int[] emoticons;
    static int maxPlusUser;
    static long maxSale;
    
    public int[] solution(int[][] users, int[] emoticons) {        
        this.users = users;
        this.emoticons = emoticons;
        int[] percents = new int[emoticons.length];
        makePercents(0, percents);
        
        return new int[]{maxPlusUser, (int) maxSale};
    }
    
    private void makePercents(int cnt, int[] percents) {
        if (cnt == emoticons.length) {
            event(percents);
            return;
        }
        
        for (int i = 0; i &amp;lt; 4; i++) {
            percents[cnt] = pers[i];
            makePercents(cnt + 1, percents);
        }
    }
    
    private void event(int[] percents) {
        // 이모티콘 구매자
        List&amp;lt;Integer&amp;gt;[] emoticonBuyers = makeEmoticonBuyers(percents);
        
        // 할인된 이모티콘 가격
        int[] emoticonPrices = new int[percents.length];
        for(int i = 0; i &amp;lt; percents.length; i++) {
            emoticonPrices[i] = emoticons[i] / 10 * percentMap.get(percents[i]);
        }
        
        // 사용자별 구매 가격 계산 (이모티콘 플러스 고려 전)
        long[] totalPricesPerUsers = new long[users.length];
        for (int i = 0; i &amp;lt; percents.length; i++) {
            List&amp;lt;Integer&amp;gt; buyers = emoticonBuyers[i];
            for (int buyer : buyers) {
                totalPricesPerUsers[buyer] += emoticonPrices[i];
            }
        }
        
        // 이모티콘 플러스 가입자 수
        boolean[] isPlusUser = new boolean[users.length];
        int plusUserCnt = 0;
        for (int i = 0; i &amp;lt; users.length; i++) {
            if (totalPricesPerUsers[i] &amp;gt;= users[i][1]) {
                isPlusUser[i] = true;
                plusUserCnt++;
            }
        }
        if (maxPlusUser &amp;gt; plusUserCnt) {
            return;
        }
        
        // 이모티콘 플러스 고려하여 판매액 계산
        long totalPrice = 0L;
        for (int i = 0; i &amp;lt; users.length; i++) {
            if (!isPlusUser[i]) {
                totalPrice += totalPricesPerUsers[i];
            }
        }
        if (maxPlusUser &amp;lt; plusUserCnt) {
            maxPlusUser = plusUserCnt;
            maxSale = totalPrice;
        } else {  // maxPlusUser == plusUserCnt 인 경우
            maxSale = Math.max(maxSale, totalPrice);  
        }
    }
    
    static List&amp;lt;Integer&amp;gt;[] makeEmoticonBuyers(int[] percents) {
        List&amp;lt;Integer&amp;gt;[] emoticonBuyers = new ArrayList[percents.length];
        for (int i = 0; i &amp;lt; percents.length; i++) {
            int percent = percents[i];
            emoticonBuyers[i] = new ArrayList&amp;lt;&amp;gt;();
            for (int j = 0; j &amp;lt; users.length; j++) {
                if (percent &amp;gt;= users[j][0]) {
                    emoticonBuyers[i].add(j);
                }
            }
        }
        return emoticonBuyers;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;13, 15, 18번 테스트케이스에서 틀렸었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부동 소수점연산은 근사값을 저장하기 때문에 이모티콘의 할인된 가격을 계산하면서 틀린 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[기존 코드]&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1742819849623&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;static final Map&amp;lt;Integer, Double&amp;gt; percentMap = Map.of(10, 0.9, 20, 0.8, 30, 0.7, 40, 0.6);

```

private void event(int[] percents) {
    ```
    // 할인된 이모티콘 가격
    int[] emoticonPrices = new int[percents.length];
    for(int i = 0; i &amp;lt; percents.length; i++) {
        emoticonPrices[i] = (int) (emoticons[i] * percentMap.get(percents[i]));
    }
    ````
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 percentMap.get(percents[i]) 를 사용해서 곱셈을 하면 double 즉, 실수값이 반환된다. 하지만, 이는 결과값이 5400 이었어도 5400.0000001 이 저장되었을 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 모조리 정수 연산으로 바꾸어서 계산하도록 수정했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[수정한 코드]&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1742819861294&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;static final Map&amp;lt;Integer, Integer&amp;gt; percentMap = Map.of(10, 9, 20, 8, 30, 7, 40, 6);

```

private void event(int[] percents) {
    ```
    // 할인된 이모티콘 가격
    int[] emoticonPrices = new int[percents.length];
    for(int i = 0; i &amp;lt; percents.length; i++) {
        emoticonPrices[i] = emoticons[i] / 10 * percentMap.get(percents[i]);
    }
    ````
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;percentMap에 저장되는 타입을 &amp;lt;Integer, Integer&amp;gt; 으로 수정하고, emoticons[i] / 10 * percentMap.get(percents[i]) 처럼 정수만 사용하도록 수정했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[기억하자]&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실수연산을 할 때는 부동소수점의 오류를 주의하자. 3.2 를 저장했어도 실제로는 3.20000000001 이 저장되어 추후 결과값이 완전히 달라질 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 다음과 같은 해결책으로 부동소수점의 오류를 피하자.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;최대한 정수로 연산하기&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;10 * 0.8&amp;nbsp; -&amp;gt;&amp;nbsp; 10 / 10 * 8&amp;nbsp; 처럼 정수만을 사용하도록 수정&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Math.round(v)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Math.round() 를 해주면 소수점 첫째 자리까지 반올림해준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이중 (혹은 그 이상의) for 문을 사용하고, 각각 인덱싱을 위한 변수로 쓰인다면 올바른 배열 혹은 리스트에 해당 인덱싱이 쓰였는지 조심!!하자.&lt;/p&gt;</description>
      <category>코딩 테스트</category>
      <category>150368</category>
      <category>이모티콘 할인행사</category>
      <category>프로그래머스</category>
      <author>한 면만 쓴 종이</author>
      <guid isPermaLink="true">https://programming-story.tistory.com/202</guid>
      <comments>https://programming-story.tistory.com/202#entry202comment</comments>
      <pubDate>Mon, 24 Mar 2025 21:49:30 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 표현 가능한 이진 트리 자바</title>
      <link>https://programming-story.tistory.com/199</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/150367&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/150367&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분할정복을 사용하는 문제입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[풀이한 코드]&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1742376626764&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

class Solution {
    public int[] solution(long[] numbers) {
        int[] answer = new int[numbers.length];
        for (int i = 0; i &amp;lt; numbers.length; i++) {
            answer[i] = getAnswer(numbers[i]);
        }
        return answer;
    }
    
    static int getAnswer(long number) {
        // 1) 십진수 -&amp;gt; 이진수 변환
        String binary = Long.toBinaryString(number);
        
        // 2) 이진수에 더미 노드 채우기
        double size = getSize(binary.length());
        StringBuilder add = new StringBuilder();
        for (int i = binary.length(); i &amp;lt; size; i++) {
            add.append(&quot;0&quot;);
        }
        binary = add.toString() + binary;
        
        // 3) 만든 트리가 올바른 트리인지 확인하기
        if (isBinaryTree(binary)) {
            return 1;
        }
        return 0;
    }
    
    static int getSize(int length) {
        int h = 1;
        while((int) Math.pow(2, h) - 1 &amp;lt; length) {
            h++;
        }
        return (int) Math.pow(2, h) - 1;
    }
    
    static boolean isBinaryTree(String tree) {
        int len = tree.length();
        if (tree.length() == 0) {
            return true;
        }
        
        int root = len / 2;
        String leftSubTree = tree.substring(0, root);
        String rightSubTree = tree.substring(root + 1);
        if (tree.charAt(root) == '0') {
            return isZeroTree(tree.substring(0, root)) &amp;amp;&amp;amp; isZeroTree(tree.substring(root + 1));
        }
        return isBinaryTree(leftSubTree) &amp;amp;&amp;amp; isBinaryTree(rightSubTree);
    }
                                                                    
    static boolean isZeroTree(String tree) {
        int len = tree.length();
        if (tree.length() == 0) return true;

        int root = len / 2;
        String leftSubTree = tree.substring(0, root);
        String rightSubTree = tree.substring(root + 1);

        if (tree.charAt(root) == '1') {
            return false;
        }

        return isZeroTree(leftSubTree) &amp;amp;&amp;amp; isZeroTree(rightSubTree);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[기억하자]&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 포화 이진 트리의 노드 수: &lt;b&gt;2 ^ (h + 1)) - 1&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 루트 노드의 레벨을 0이라고 생각했을 때의 공식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 루트 노드의 레벨을 1이라고 생각하면 &lt;b&gt;2 ^ h - 1&lt;/b&gt; 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 자바로 하면, &lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;(int) Math.pow(2, h) - 1 &amp;lt; length&lt;/b&gt;&lt;/span&gt; 이다. Math.pow() 의 반환값은 double 이기 때문에 (int) 로 강제 형변환할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Long.&lt;b&gt;toBinaryString(num)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Integer.toBinaryString(num)도 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이진수로 변환해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. &lt;b&gt;String.substring(int st, int en)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- string의 s는 대문자가 아니라 소문자이다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 트리에서 분할정복 방법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 트리를 오른쪽 트리와 왼쪽 트리로 나눈다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 왼쪽 트리와 오른쪽 트리를 재귀함수로 다시 넣어서 반복한다.&lt;/p&gt;
&lt;pre id=&quot;code_1742384218041&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private static boolean dfs(String number) {
    boolean valid = true;

    int mid = (number.length()-1)/2;
    char root = number.charAt(mid);
    String left = number.substring(0,mid);
    String right = number.substring(mid+1,number.length());

    if(root == '0' &amp;amp;&amp;amp; (left.charAt((left.length()-1)/2)=='1' || right.charAt((right.length()-1)/2)=='1')){
        return false;
    }
    
    valid = dfs(left);
    if (valid) {
        valid = dfs(right);
    }

    if(left.length() &amp;gt;= 3) {  // 리프노드는 0이어도 상관없기 때문에 길이가 3이상일 때만 탐색
        valid = dfs(left);
        if(valid) {
            valid = dfs(right);
        }
    }
    return valid;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>코딩 테스트</category>
      <author>한 면만 쓴 종이</author>
      <guid isPermaLink="true">https://programming-story.tistory.com/199</guid>
      <comments>https://programming-story.tistory.com/199#entry199comment</comments>
      <pubDate>Wed, 19 Mar 2025 20:41:52 +0900</pubDate>
    </item>
    <item>
      <title>[백준] 우주신과의 교감 1774번 자바</title>
      <link>https://programming-story.tistory.com/198</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1774&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1774&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적인 MST 문제입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;최소신장트리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래프의 모든 정점을 사이클 없이 잇는 트리에서 간선의 가중치의 합이 최소가 되는 트리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;크루스칼 알고리즘&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간선을 하나씩 늘려가면서 이어줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[풀이한 코드]&lt;/b&gt;&lt;/h4&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;package mst;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class B1774 {
    static class Node {
        int x;
        int y;
        Node(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    static class Edge implements Comparable&amp;lt;Edge&amp;gt; {
        int a;
        int b;
        double dist;
        public Edge(int a, int b, double dist) {
            this.a = a;
            this.b = b;
            this.dist = dist;
        }

        @Override
        public int compareTo(Edge o) {
            return Double.compare(this.dist, o.dist);
        }
    }
    static int[] parents;
    static Node[] nodes;
    static int N;
    static int M;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        nodes = new Node[N + 1];
        parents = new int[N + 1];
        for (int i = 0; i &amp;lt; N; i++) {
            st = new StringTokenizer(br.readLine());
            int x = Integer.parseInt(st.nextToken());
            int y = Integer.parseInt(st.nextToken());
            nodes[i + 1] = new Node(x, y);
            parents[i + 1] = i + 1;
        }

        for (int i = 0; i &amp;lt; M; i++) {
            st = new StringTokenizer(br.readLine());
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());
            unionParent(a, b);
        }

        PriorityQueue&amp;lt;Edge&amp;gt; pq = new PriorityQueue&amp;lt;&amp;gt;();
        for (int i = 1; i &amp;lt;= N; i++) {
            for (int j = 1; j &amp;lt;= N; j++) {
                double cost = Math.sqrt(Math.pow(nodes[i].x - nodes[j].x, 2) + Math.pow(nodes[i].y - nodes[j].y, 2));
                pq.add(new Edge(i, j, cost));
            }
        }
        double cost = 0;
        while (!pq.isEmpty()) {
            Edge edge = pq.poll();
            if (findParent(edge.a) != findParent(edge.b)) {
                unionParent(edge.a, edge.b);
                cost += edge.dist;
            }
        }
        System.out.printf(&quot;%.2f&quot;, cost);
    }

    static void unionParent(int a, int b) {
        a = findParent(a);
        b = findParent(b);
        if (a &amp;lt; b) {
            parents[b] = a;
        } else {
            parents[a] = b;
        }
    }

    static int findParent(int x) {
        if (parents[x] == x) {
            return x;
        }
        return parents[x] = findParent(parents[x]);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[시간복잡도]&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 이미 연결된 간선 처리&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- M개의 이미 연결된 간선을 처리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이때, Union Find 알고리즘을 사요했습니다. 해당 알고리즘은 &lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;O(1)&lt;/b&gt;&lt;/span&gt;에 가까운 시간복잡도를 갖습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;2. 모든 노드 간 거리를 우선순위 큐에 삽입&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 우선순위 큐에 삽입하는 연산: &lt;b&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;O(logN)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 이중 반복문을 돌리며 우선순위 큐에 삽입하는 연산: &lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;O(N^2 logN)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 크루스칼 알고리즘&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 우선순위 큐에서 poll() 연산: O(logN)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- unionParent() 연산: O(1) 에 가까움&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; N^2 번 수행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; &lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;O(N^2 logN)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 최종 시간복잡도는 &lt;span style=&quot;background-color: #f3c000;&quot;&gt;&lt;b&gt;O(N^2 logN)&lt;/b&gt;&lt;/span&gt; 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[기억하자]&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. inner class 의 비교 방법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Comparable&amp;lt;Edge&amp;gt; 를 implements하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- @Override public int compareTo() 구현&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;static class Edge implements Comparable&amp;lt;Edge&amp;gt; {
    int a;
    int b;
    double dist;
    public Edge(int a, int b, double dist) {
        this.a = a;
        this.b = b;
        this.dist = dist;
    }

    @Override
    public int compareTo(Edge o) {
        return Double.compare(this.dist, o.dist);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 제곱할 때 x * x는 오버플로 발생 가능성이 있기 때문에 Math.pow() 사용하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 단, 반환값은 항상 double이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Math.pow(x, 2) 를 하면 x의 2제곱&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 출력할 때 소수점 2번째 자리까지 반올림하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- System.out.&lt;b&gt;printf&lt;/b&gt;(&quot;%.2f&quot;, 수);&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>코딩 테스트</category>
      <author>한 면만 쓴 종이</author>
      <guid isPermaLink="true">https://programming-story.tistory.com/198</guid>
      <comments>https://programming-story.tistory.com/198#entry198comment</comments>
      <pubDate>Wed, 19 Mar 2025 13:37:19 +0900</pubDate>
    </item>
    <item>
      <title>Mac에 Oracle 19c 버전 설치 (ORA-12526 오류 해결)</title>
      <link>https://programming-story.tistory.com/197</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;제 맥은 M2 칩입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;[1] Colima 설치&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[1-1] colima를 설치합니다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #dddddd; color: #ef5369;&quot;&gt;&lt;b&gt;$ brew install colima&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사전에 brew가 설치되어 있어야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[1-2] Colima를 실행합니다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #dddddd; color: #ef5369;&quot;&gt;&lt;b&gt;$ colima start --memory 4 --arch x86_64&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; $ docker context ls 명령을 통해 colima 옆에 * 표시로 실행되고 있는지 확인해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;[2] oracle-19c 설치하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[2-1] docker image pull 받기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #dddddd; color: #ef5369;&quot;&gt;&lt;b&gt;$ docker pull doctorkirk/oracle-19c&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;docker images&lt;/b&gt; 명령어를 통해 받은 이미지를 확인하실 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;43&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnAtl5/btsMx3PiSed/QfGZqXhhuneW9S1qQzaZm1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnAtl5/btsMx3PiSed/QfGZqXhhuneW9S1qQzaZm1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnAtl5/btsMx3PiSed/QfGZqXhhuneW9S1qQzaZm1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnAtl5%2FbtsMx3PiSed%2FQfGZqXhhuneW9S1qQzaZm1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;652&quot; height=&quot;43&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;43&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;[3] 디렉토리 생성&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[3-1] 디렉토리 이동&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369; background-color: #dddddd;&quot;&gt;&lt;b&gt;$ mkdir -p /{내가 원하는 디렉토리}/oracle-19c/oradata&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 /{내가 원하는 디렉토리} 로 이동합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[3-2] 소유자 변경&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ef5369; background-color: #dddddd;&quot;&gt;$ sudo chown -R 54321:54321 .oracle-19c&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;[4] 컨테이너 만들기&lt;/h2&gt;
&lt;pre class=&quot;haml&quot;&gt;&lt;code&gt;    docker run --name oracle-19c \\
    -p 1521:1521 \\
    -e ORACLE_SID=ORCL \\
    -e ORACLE_PWD=1234 \\
    -e ORACLE_CHARACTERSET=KO16MSWIN949 \\
    -v /**{내가 원하는 디렉토리}**/oracle-19c/oradata/:/opt/oracle/oradata doctorkirk/oracle-19c
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 하면 아마 시간이 아 좀 너무한데? 싶을 정도로 오래 걸리는 분이 계실 겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그때는 &lt;span style=&quot;color: #ef5369; background-color: #dddddd;&quot;&gt;docker ps&lt;/span&gt; 명령을 통해 실행중인 컨테이너를 확인합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령을 통해 나온 STATUS 컬럼값의 괄호 안 값이 &lt;b&gt;health: starting&lt;/b&gt; 이면 아직 더 기다리셔야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, &lt;b&gt;healthy&lt;/b&gt; 이면 그냥 다음 단계로 이동하셔도 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 새로 터미널 창을 열어서 진행했습니다. 컨테이너 생성중이라던 터미널은 아직도 저러고 있네요..&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;425&quot; data-origin-height=&quot;140&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmxFsL/btsMxoM5pBZ/DckLF2beKUq6rkoXJ0tJG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmxFsL/btsMxoM5pBZ/DckLF2beKUq6rkoXJ0tJG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmxFsL/btsMxoM5pBZ/DckLF2beKUq6rkoXJ0tJG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmxFsL%2FbtsMxoM5pBZ%2FDckLF2beKUq6rkoXJ0tJG1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;425&quot; height=&quot;140&quot; data-origin-width=&quot;425&quot; data-origin-height=&quot;140&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;[5] Bash로 접속해서 SQL 명령&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[5-1] &lt;b&gt;&lt;span style=&quot;color: #ef5369; background-color: #dddddd;&quot;&gt;$ docker exec -it oracle-19c bash&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bash 로 컨테이너를 접속해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[5-2] oracleDB에 사용자 생성&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;	ALTER SESSION SET &quot;_ORACLE_SCRIPT&quot;=true;
    
  CREATE USER oracleuser identified by oraclepassword;  #username과 password는 원하는거 하십쇼
  
  grant connect, resource to oracleuser;
  
  alter user oracleuser quota unlimited on users;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;[6] DBeaver에서 연결&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[6-1] DBeaver 설치&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://dbeaver.io/download/&quot;&gt;https://dbeaver.io/download/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 링크에 들어가셔서 Mac OS X 를 설치합니다. 저는 그 중 `MacOS for Apple Sillicon (dmg) 라고 적혀 있는 것을 다운 받았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에는 dmg 파일 풀어서 Applications에 넣으라면 넣고 실행하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[6-2] Oracle DB 연결하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;DBeaver에서 설치하란 것은 전부 설치해줬습니다. 설치 안한다 했더니 오류를 뱉더라고요..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 왼쪽 상단의 콘센트 모양을 클릭하여 Connect to a database 창에서 Oracle을 선택해줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;893&quot; data-origin-height=&quot;438&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n01gS/btsMvS9sHrA/ceFoYW3SfofzIb9SZJQHKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n01gS/btsMvS9sHrA/ceFoYW3SfofzIb9SZJQHKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n01gS/btsMvS9sHrA/ceFoYW3SfofzIb9SZJQHKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn01gS%2FbtsMvS9sHrA%2FceFoYW3SfofzIb9SZJQHKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;893&quot; height=&quot;438&quot; data-origin-width=&quot;893&quot; data-origin-height=&quot;438&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 설정해줍니다. 특히 Database 줄에서 SID로 변경해주는 것 잊으시면 안됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러고 Test Connection을 해줍니다. 저는 이때 매우 콩닥거렸죠. 그리고 절망했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 다음과 같은 오류가 뜨는 분이 계신다면 침착하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ORA-12526: TNS:리스너: 적절한 모든 인스턴스가 제한 모드입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 sqlplus에 접속했던 터미널 창으로 돌아갑니다. 그리고 다음 명령어를 입력하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369; background-color: #dddddd;&quot;&gt;&lt;b&gt;SELECT LOGINS FROM V$INSTANCE;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 &lt;b&gt;RESTRICTED&lt;/b&gt;라고 뜰겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ef5369; background-color: #dddddd;&quot;&gt;ALTER SYSTEM DISABLE RESTRICTED SESSION; &lt;/span&gt;&lt;/b&gt;입력하고 다시 Test Connection 하면 아래와 같이 정상적으로 뜰겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;901&quot; data-origin-height=&quot;631&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oxAKx/btsMv3wheOY/AmoNAdAf4b78cAdmt5PFY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oxAKx/btsMv3wheOY/AmoNAdAf4b78cAdmt5PFY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oxAKx/btsMv3wheOY/AmoNAdAf4b78cAdmt5PFY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoxAKx%2FbtsMv3wheOY%2FAmoNAdAf4b78cAdmt5PFY1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;901&quot; height=&quot;631&quot; data-origin-width=&quot;901&quot; data-origin-height=&quot;631&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;읽어주셔서 감사하고 도움이 되셨길 바랍니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 2만~&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ps. 오류가 난다면 모두 지우고 처음부터 다시 시도해 보세요..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 5번정도 ^^ 시도한 것 같습니다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 제가 기재한 모든 과정을 !!똑같이!! 하시길 추천드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아.. 이건 아닌 것 같은데.. 라는 생각으로 몇 과정을 조금씩 수정하다가는.. 저처럼 5번&amp;hellip;.을 하게 되실 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[참고]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://lovethefeel.tistory.com/124&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://lovethefeel.tistory.com/124&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@ccorgi1997/Mac-M1-%EB%A7%A5%EB%B6%81%EC%97%90%EC%84%9C-Oracle-11-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://velog.io/@ccorgi1997/Mac-M1-%EB%A7%A5%EB%B6%81%EC%97%90%EC%84%9C-Oracle-11-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://hard-carry.com/way-to-install-oracledb-on-silicon-mac-m2&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://hard-carry.com/way-to-install-oracledb-on-silicon-mac-m2&lt;/a&gt;&lt;/p&gt;</description>
      <category>ora-12526</category>
      <category>oracle-19</category>
      <author>한 면만 쓴 종이</author>
      <guid isPermaLink="true">https://programming-story.tistory.com/197</guid>
      <comments>https://programming-story.tistory.com/197#entry197comment</comments>
      <pubDate>Tue, 25 Feb 2025 23:54:25 +0900</pubDate>
    </item>
    <item>
      <title>브라우저에 네이버 URL을 입력했을 때 벌어지는 일</title>
      <link>https://programming-story.tistory.com/196</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[요약]&lt;/b&gt;&lt;/h4&gt;&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;&lt;li&gt;URL 파싱 → 캐싱된 DNS 기록 확인 → DNS 조회&lt;/li&gt;&lt;li&gt;라우터를 통해 해당 서버의 게이트웨이까지 이동 -&amp;gt; ARP를 통해 IP 주소를 MAC 주소로 변환 네이버 서버 도달&lt;/li&gt;&lt;li&gt;대상 서버와 TCP 소켓 연결 -&amp;gt; HTTP(HTTPS) 프로토콜 요청 &amp;amp; 응답 -&amp;gt; 브라우저에서 응답 해석해서 보여준다!&lt;/li&gt;&lt;/ol&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[1] URL 파싱&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;프로토콜, 호스트 이름, 경로, 포트 등으로 URL의 구조를 해석합니다.&lt;br&gt;이때 파싱한 호스트 이름을 캐싱된 DNS 기록 확인 단계에서 사용합니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[2] 캐싱된 DNS 기록 확인&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저는 DNS 해석 과정을 단축하기 위해 캐싱된 DNS 기록을 먼저 확인합니다.&lt;br&gt;캐시에 IP주소가 존재하면, DNS 쿼리를 추가하지 않고, 바로 연결을 시도합니다.&lt;br&gt;- 브라우저 캐시 -&amp;gt; OS 캐시 -&amp;gt; 라우터 캐시 -&amp;gt; ISP 캐시 순서로 확인합니다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[3] DNS 조회&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;캐시에 해당 URL(호스트 네임)이 존재하지 않으면, DNS 서버에 요청해 해당 URL을 IP 주소로 변환합니다.&lt;br&gt;이때 DNS란, 도메인 이름과 IP 주소를 &lt;b&gt;매핑&lt;/b&gt;해주는 서버입니다.&lt;br&gt;&lt;b&gt;[DNS 서버로 요청하는 과정]&lt;/b&gt;&lt;br&gt;[Root DNS] → [.com DNS] → [.naver DNS] → [.www DNS]&lt;br&gt;위와 같은 과정을 거쳐 완벽한 주소를 찾아 IP 주소를 매핑합니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[4] 라우터를 통해 해당 서버의 게이트웨이까지 이동&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #787774;&quot;&gt;&lt;i&gt;*게이트웨이: 서로 다른 통신망, 프로토콜을 사용하는 네트워크 간의 통신을 가능하게 하는 컴퓨터나 SW를 두루 일컫는 용어&lt;/i&gt;&lt;/span&gt;&lt;br&gt;DNS 서버한테 IP 주소를 받았으니 해당 서버로 요청을 보냅니다.&lt;br&gt;이 요청은 네트워크 장비인 라우터의 라우팅을 통해 네트워크를 타고 이루어집니다.&lt;br&gt;각각의 라우터에 있는 라우팅 테이블의 IP를 기반으로 패킷을 전달해 나갑니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[5] ARP를 통해 IP 주소를 MAC 주소로 변환&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #787774;&quot;&gt;&lt;i&gt;*ARP: IP 주소로부터 MAC 주소를 구하는 IP와 MAC 주소의 다리 역할을 하는 프로토콜&lt;/i&gt;&lt;/span&gt;&lt;br&gt;실질적인 통신을 하기 위해서는 논리 주소인 IP 주소를 물리 주소인 MAC 주소로 변환해야 합니다.&lt;br&gt;이를 위해 해당 네트워크 내에서 ARP 요청을 브로드캐스팅합니다.&lt;br&gt;해당 IP 주소를 가지고 있는 서버는 자신의 MAC 주소를 응답합니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;이로써 실제 네이버의 서버에 도달하게 됩니다!&lt;/b&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[6] 대상 서버와 TCP 소켓 연결&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;찾은 대상 서버와 통신하기 위해 TCP 소켓 연결을 진행합니다.&lt;br&gt;소켓 연결은 3-way handshake 과정을 통해 이루어집니다.&lt;br&gt;HTTPS 요청인 경우 암호화 통신을 위한 TLS 핸드쉐이킹을 추가합니다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;531&quot; data-origin-height=&quot;604&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWL4Cv/btsMk3bpEeP/0heXlObvBsTkpJNJknFEW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWL4Cv/btsMk3bpEeP/0heXlObvBsTkpJNJknFEW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWL4Cv/btsMk3bpEeP/0heXlObvBsTkpJNJknFEW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWL4Cv%2FbtsMk3bpEeP%2F0heXlObvBsTkpJNJknFEW1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;423&quot; height=&quot;481&quot; data-origin-width=&quot;531&quot; data-origin-height=&quot;604&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[7] HTTP(HTTPS) 프로토콜 요청 &amp;amp; 응답&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;연결이 되었으니 해당 페이지(www.naver.com)를 달라고 서버에 요청합니다.&lt;br&gt;서버는 요청에 대한 응답을 생성하여 브라우저에 전달합니다.&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[8] 브라우저에서 응답 해석&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;서버의 응답 내용은 HTML, CSS, Javascript 등으로 이루어져 있습니다.&lt;br&gt;따라서 일반 사용자도 볼 수 있도록 이를 해석하여 페이지를 보여주게 됩니다!&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;최근에 면접을 봤습니다. 해당 기업에서 정말 많은.. 질문을 받았습니다. 2:1 면접이었는데 1시간 넘게.. 봤어요..&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;30분 넘어가니까 목이 건조해져서 말하다가 쇳소리까지 났습니다. (+ 긴장해서 목탄것두 잇서용 ㅎㅎ)&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;아무튼 CS 관련 질문도 매우 많이 받았고.. 제대로 대답하지 못한 질문도 많았어요. 많이 아쉽지만 CS 공부를 더 열심히 하게 된 계기가 되었습니다 :) 굳&lt;/span&gt;&lt;/p&gt;</description>
      <category>CS</category>
      <author>한 면만 쓴 종이</author>
      <guid isPermaLink="true">https://programming-story.tistory.com/196</guid>
      <comments>https://programming-story.tistory.com/196#entry196comment</comments>
      <pubDate>Sun, 16 Feb 2025 22:38:52 +0900</pubDate>
    </item>
    <item>
      <title>PriorityQueue forEach() 는 정렬되어 조회되지 않는다?!</title>
      <link>https://programming-story.tistory.com/195</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘의 주제는&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size16&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;PriorityQueue의 forEach 메서드의 조회 순서&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여느때와 같이 알고리즘 문제를 풀고 있었는데..&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/12764&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/12764&lt;br /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;i&gt;- 문제 보고 오세용&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자꾸 내 코드가 맞는데 틀렸다고~ 틀렸다고~ 하는거 아닙니까.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진심으로다가 집 가야되는데 계속 틀렸다니까 집도 못 가고! 밥도 못 먹고! ㅠㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 제가 작성했던 답은 아래와 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러분들을 위해 주석을 꼼꼼히 달아봤어용.&lt;/p&gt;
&lt;pre id=&quot;code_1739440698278&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
    // 종료 시간 기준 후보
    static PriorityQueue&amp;lt;int[]&amp;gt; timeCandis = new PriorityQueue&amp;lt;&amp;gt;((c1, c2) -&amp;gt; c1[0] - c2[0]);  // 종료 시간, 좌석 번호
    // 테이블 번호 기준 후보
    static PriorityQueue&amp;lt;int[]&amp;gt; tableCandis = new PriorityQueue&amp;lt;&amp;gt;((c1, c2) -&amp;gt; c1[1] - c2[1]);  // 종료 시간, 좌석 번호

    public static void main(String[] args) throws IOException {
    	// 입력
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        StringBuilder sb = new StringBuilder();
        int N = Integer.parseInt(br.readLine());
        List&amp;lt;int[]&amp;gt; times = new ArrayList&amp;lt;&amp;gt;();  // 시작 시간, 종료 시간
        for (int i = 0; i &amp;lt; N; i++) {
            st = new StringTokenizer(br.readLine());
            times.add(new int[]{Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken())});
        }
        
        // 싸지방 사용 시간 정렬 (시작 시간 기준)
        times.sort(Comparator.comparingInt(t -&amp;gt; t[0]));

        int idx = 0;
        int[] tables = new int[N];  // 자리 사용 횟수 저장 배열
        tables[idx]++;
        timeCandis.add(new int[]{times.get(0)[1], idx++});

        for (int i = 1; i &amp;lt; N; i++) {
            int[] now = times.get(i);
            // 시간 변경 + 사람 더 앉음 -&amp;gt; time &amp;amp; table candidates 다시 검사해줌
            checkEndTime(now[0]);

            // idx 전에 빈 자리가 있으면 해당 자리에 앉힘
            // 사람이 앉으면 timeCandis에 무조건 넣음
            if (!tableCandis.isEmpty()) {
                int[] candi = tableCandis.poll();
                timeCandis.add(new int[]{now[1], candi[1]});
                tables[candi[1]]++;
            } else {  // idx 전에 빈 자리 없으면 idx에 앉히고 하나 늘림
                tables[idx]++;
                timeCandis.add(new int[]{now[1], idx});
                idx++;
            }
        }
		
        // 출력
        sb.append(idx).append(&quot;\n&quot;);
        for (int i = 0; i &amp;lt; idx; i++) {
            sb.append(tables[i]).append(&quot; &quot;);
        }
        System.out.println(sb);
    }

    static void checkEndTime(int now) {
        int cnt = 0;
        // 우선순위 큐인 timeCandis에서 하나씩 조회 -&amp;gt; 종료 시간이 현재 시간보다 적은 것.
        // 즉, 이미 사용 종료된 자리 정보는 사용 가능한 자리이기 때문에 tableCandis에 넣음
        // tableCandis에 넣은 만큼 timeCandis에서 빼기위해 cnt 세줌.
        for (int[] time : timeCandis) {
            if (time[0] &amp;lt; now) {
                tableCandis.add(time);
                cnt++;
            } else {
                break;
            }
        }
        // cnt 만큼 timeCandis에서 빼줌
        for (int i = 0; i &amp;lt; cnt; i++) {
            timeCandis.poll();
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 부분은 checkEndTime 메서드입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 우선순위 큐를 forEach로 조회하면 우선순위대로 (순서대로) 조회될 거라고 생각했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 PriorityQueue를 forEach는 순서대로 조회되지 않습니다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 그 이유를 알아보겠습니당.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PriorityQueue의 forEach메서드를 보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-02-13 오후 10.35.54.png&quot; data-origin-width=&quot;1290&quot; data-origin-height=&quot;598&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lMjF4/btsMh6fhSGT/127yOKBsZ3uQaW5wKqP6y1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lMjF4/btsMh6fhSGT/127yOKBsZ3uQaW5wKqP6y1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lMjF4/btsMh6fhSGT/127yOKBsZ3uQaW5wKqP6y1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlMjF4%2FbtsMh6fhSGT%2F127yOKBsZ3uQaW5wKqP6y1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;612&quot; height=&quot;284&quot; data-filename=&quot;스크린샷 2025-02-13 오후 10.35.54.png&quot; data-origin-width=&quot;1290&quot; data-origin-height=&quot;598&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;es라는 배열을 순서대로 조회하는데 es는 queue네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 이제 queue를 보겟슴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-02-13 오후 10.44.25.png&quot; data-origin-width=&quot;1634&quot; data-origin-height=&quot;606&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cln40V/btsMgKEo3WF/b9CART1XgKklf9markrTok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cln40V/btsMgKEo3WF/b9CART1XgKklf9markrTok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cln40V/btsMgKEo3WF/b9CART1XgKklf9markrTok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcln40V%2FbtsMgKEo3WF%2Fb9CART1XgKklf9markrTok%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;717&quot; height=&quot;266&quot; data-filename=&quot;스크린샷 2025-02-13 오후 10.44.25.png&quot; data-origin-width=&quot;1634&quot; data-origin-height=&quot;606&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저같은 사람을 위해 상세하게 주석 설명이 있네요.. 고마워라&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 작은 값(우선순위 0번째)의 인덱스가 0인 것은 맞습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 제가 간과한 부분! 우선순위 큐는 힙이기 때문에 완전 이진 트리 구조입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오름 차순을 정렬 기준으로 했을 때, 부모 노드는 자식 노드보다 클 수 없죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것은 트리를 순서대로 방문하면 되는 완전히 정렬된 상태는 아니라는 것을 뜻합니다. (첫 노드는 최솟값이라는 것은 보장 가능. 무조건 보장!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 위의 설명에 있듯이 queue 배열은 그저 트리를 배열에 담은 것 뿐입니다. 순서대로 말이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러니까 queue[n]의 자식이 queue[2 * n + 1]과 queue[2 * (n + 1)] 인 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 우선순위 큐 자료구조의 특성은 제끼고 그냥 아~ 우선순위니까 차례대로 조회하게 해주겠지~ .... 라고 생각하고 위와 같은 코드를 짜게 됐던 것입니다. 허허 뭐든 잘 알고 사용하는게 정말정말.. 중요하죠&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 제가 짠 코드를 고쳐봐야겠죠잉?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739441687859&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Main {
    // 종료 시간 기준 후보
    static PriorityQueue&amp;lt;int[]&amp;gt; timeCandis = new PriorityQueue&amp;lt;&amp;gt;((c1, c2) -&amp;gt; c1[0] - c2[0]);  // 종료 시간, 좌석 번호
    // 테이블 번호 기준 후보
    static PriorityQueue&amp;lt;int[]&amp;gt; tableCandis = new PriorityQueue&amp;lt;&amp;gt;((c1, c2) -&amp;gt; c1[1] - c2[1]);  // 종료 시간, 좌석 번호

    public static void main(String[] args) throws IOException {
        ```
    }

    static void checkEndTime(int now) {
        while (!timeCandis.isEmpty()) {
            int[] time = timeCandis.peek(); // [1]
            if (time[0] &amp;lt; now) {
                tableCandis.add(time);
                timeCandis.poll();  // [2]
            } else {
                break;  // [3]
            }
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[1]&lt;/b&gt; peek()로 timeCandis의 첫 노드. 즉, 종료 시간이 가장 빠른 노드를 가져옵니다. 이 종료 시간이 현재 시간 이전이면 해당 자리는 빈 자리인 것이죠&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[2]&lt;/b&gt; 그럼 해당 노드는 빼줘야 합니다. 왜냐? tableCandis에 넣어줘야 하거든요. 여기는 비어있는 자리를 저장하는 우선순위 큐 공간이랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[3]&lt;/b&gt; 만약 timeCandis에서 peek()로 조회한 &lt;u&gt;종료 시간이 가장 빠른 노드&lt;/u&gt;가 &lt;u&gt;현재 시간보다 이후 시간&lt;/u&gt;이면 더이상 해당 큐에는 &lt;u&gt;현재 시간보다 빠른 노드는 존재하지 않는&lt;/u&gt; 거겠죠잉? 그럼 그~냥 바로 해당 반복문을 탈출!하는겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 해서 백준 싸지방에 간 준하 문제는 해결되었습니다. 짜란~&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-02-13 오후 11.15.52.png&quot; data-origin-width=&quot;1161&quot; data-origin-height=&quot;308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kUEb5/btsMgIzRGDL/KWLBlsBLHxhD2g1e7LCeyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kUEb5/btsMgIzRGDL/KWLBlsBLHxhD2g1e7LCeyk/img.png&quot; data-alt=&quot;정말.. 다양한.. 시도들을 해봤어요.. 이건가? 하면서 고치다가 시간초과까지 나버림. 하핫&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kUEb5/btsMgIzRGDL/KWLBlsBLHxhD2g1e7LCeyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkUEb5%2FbtsMgIzRGDL%2FKWLBlsBLHxhD2g1e7LCeyk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1161&quot; height=&quot;308&quot; data-filename=&quot;스크린샷 2025-02-13 오후 11.15.52.png&quot; data-origin-width=&quot;1161&quot; data-origin-height=&quot;308&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;정말.. 다양한.. 시도들을 해봤어요.. 이건가? 하면서 고치다가 시간초과까지 나버림. 하핫&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정말 왜 통과 못하는지 도무지 모르겠었는데 해결해서 기분이 좋네용. 햅삐~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JAVA</category>
      <category>12764</category>
      <category>priorityqueue</category>
      <category>백준</category>
      <category>우선순위 큐</category>
      <author>한 면만 쓴 종이</author>
      <guid isPermaLink="true">https://programming-story.tistory.com/195</guid>
      <comments>https://programming-story.tistory.com/195#entry195comment</comments>
      <pubDate>Thu, 13 Feb 2025 23:18:11 +0900</pubDate>
    </item>
    <item>
      <title>[Django] 프로젝트 만들기</title>
      <link>https://programming-story.tistory.com/192</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;[1] 프로젝트 생성하기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 깃허브에 레포를 하나 팠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 해당 레포를 클론받고, 터미널에서 클론받은 로컬 위치로 이동한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. `python3 -m venv venv` 를 입력한다. (두번째 venv는 본인이 지정하면 된다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. `source venv/bin/activate` 를 입력한다. 이를 통해 가상환경을 활성화한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. `&lt;span&gt;pip install django djangorestframework` 를 입력하여 drf 패키지를 설치한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;6. `&lt;/span&gt;&lt;span&gt;django-admin startproject myapi .` 를 입력하여 프로젝트를 생성한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;ls 를 입력하여 확인해보면 아래와 같이 폴더가 생성된 것을 확인할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-01-03 오전 12.32.00.png&quot; data-origin-width=&quot;479&quot; data-origin-height=&quot;23&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XLRrI/btsLCsjlr2S/l28tTOhdy1pHAfsDIWo0d1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XLRrI/btsLCsjlr2S/l28tTOhdy1pHAfsDIWo0d1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XLRrI/btsLCsjlr2S/l28tTOhdy1pHAfsDIWo0d1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXLRrI%2FbtsLCsjlr2S%2Fl28tTOhdy1pHAfsDIWo0d1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;479&quot; height=&quot;23&quot; data-filename=&quot;스크린샷 2025-01-03 오전 12.32.00.png&quot; data-origin-width=&quot;479&quot; data-origin-height=&quot;23&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. 장고를 설치한다. 새로운 터미널을 열어서 `pip install django` 를 입력한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8. `pip list` 를 입력하여 Django 가 있는지 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9. 다시 프로젝트가 있는 터미널로 이동하여 `&lt;span&gt;python manage.py startapp backend` 를 입력하여 앱을 만든다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;10. 이제 해당 경로를 IDE에서 열어서 개발하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;[2] 기본 설정&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;1. settings.py에서 ALLOWED_HOSTS 를 모두 열어준다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1735834132315&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ALLOWED_HOSTS = ['*']&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;2. settings.py에서 TIME_ZONE 을 한국으로 변경한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1735834203896&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;TIME_ZONE = &quot;Asia/Seoul&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. settings.py에서 STATIC_URL 밑에 아래 코드를 추가한다. 이를 통해 정적 파일 관리에 대한 선언을 한 것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1735834358739&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;STATIC_URL = &quot;static/&quot;
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. settings.py에서 INSTALLED_APPS 에 이전에 만든 &quot;backend&quot; 와 &quot;rest_framework&quot;를 추가한다.&lt;/p&gt;
&lt;pre id=&quot;code_1735834473020&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;INSTALLED_APPS = [
    &quot;django.contrib.admin&quot;,
    &quot;django.contrib.auth&quot;,
    &quot;django.contrib.contenttypes&quot;,
    &quot;django.contrib.sessions&quot;,
    &quot;django.contrib.messages&quot;,
    &quot;django.contrib.staticfiles&quot;,
    &quot;backend&quot;,
    &quot;rest_framework&quot;,
]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 파이참에서 터미널을 열어서 `python manage.py makemigrations` 을 입력한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 이때 ModuleNotFoundError: No module named 'rest_framework' 이라는 오류가 났다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;찾아보니 가상환경에는 DRF가 설치되었는데 내 로컬에는 설치되어있지 않아서 이러한 오류가 뜨는 것 같았다. 그래서 로컬에도 `&lt;span&gt;pip install django djangorestframework` 를 통해 설치했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이렇게 하니 아래와 같이 오류가 사라졌다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-01-03 오전 1.27.09.png&quot; data-origin-width=&quot;746&quot; data-origin-height=&quot;42&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ani2H/btsLDG1ZOG7/ZdUIfcQh4LS7F4n8QRo9j0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ani2H/btsLDG1ZOG7/ZdUIfcQh4LS7F4n8QRo9j0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ani2H/btsLDG1ZOG7/ZdUIfcQh4LS7F4n8QRo9j0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAni2H%2FbtsLDG1ZOG7%2FZdUIfcQh4LS7F4n8QRo9j0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;746&quot; height=&quot;42&quot; data-filename=&quot;스크린샷 2025-01-03 오전 1.27.09.png&quot; data-origin-width=&quot;746&quot; data-origin-height=&quot;42&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. 터미널에 `python manage.py makemigrations` 및 `python manage.py runserver` 를 입력한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 다음과 같이 서버가 실행된 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-01-03 오전 1.45.31.png&quot; data-origin-width=&quot;2556&quot; data-origin-height=&quot;1522&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dTfzEy/btsLCtiev3q/A6nfrmDMxK2lRkA24E8n20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dTfzEy/btsLCtiev3q/A6nfrmDMxK2lRkA24E8n20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dTfzEy/btsLCtiev3q/A6nfrmDMxK2lRkA24E8n20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdTfzEy%2FbtsLCtiev3q%2FA6nfrmDMxK2lRkA24E8n20%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;779&quot; height=&quot;464&quot; data-filename=&quot;스크린샷 2025-01-03 오전 1.45.31.png&quot; data-origin-width=&quot;2556&quot; data-origin-height=&quot;1522&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Django</category>
      <author>한 면만 쓴 종이</author>
      <guid isPermaLink="true">https://programming-story.tistory.com/192</guid>
      <comments>https://programming-story.tistory.com/192#entry192comment</comments>
      <pubDate>Fri, 3 Jan 2025 04:06:28 +0900</pubDate>
    </item>
  </channel>
</rss>