<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>haing3_3.log</title>
        <link>https://velog.io/</link>
        <description>따뜻한 시선으로 세상을 변화시키는 데이터사이언티스트</description>
        <lastBuildDate>Fri, 05 Dec 2025 08:40:56 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>haing3_3.log</title>
            <url>https://velog.velcdn.com/images/haing3_3/profile/66c361b7-cd9d-41d2-b150-16914e0e76da/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. haing3_3.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/haing3_3" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[코테 매일 풀기 20일차] 1205 ]]></title>
            <link>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-20%EC%9D%BC%EC%B0%A8-1205</link>
            <guid>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-20%EC%9D%BC%EC%B0%A8-1205</guid>
            <pubDate>Fri, 05 Dec 2025 08:40:56 GMT</pubDate>
            <description><![CDATA[<h2 id="백준-1316-그룹단위체커"><a href="https://www.acmicpc.net/problem/1316">백준 1316 그룹단위체커</a></h2>
<pre><code class="language-java">package boj_silver.p1316_그룹단위체커;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.Set;
import java.util.Stack;

public class Main {
    public static void main(String[] args) throws IOException {
        int cnt = 0;
        BufferedReader br  = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());

        for (int i = 0; i&lt; N ; i++) {
            String line = br.readLine();
            Set&lt;Character&gt; set = new HashSet&lt;&gt;();
            boolean isTrue = true;

            for (int j = 0; j &lt; line.length(); j++) {
                char c = line.charAt(j);
                //이전 문자와 다르면
                if (j &gt; 0 &amp;&amp; c != line.charAt(j - 1)) {
                    //이미 나온 문자인지 확인
                    if (set.contains(c)) {
                        isTrue = false;
                        break;
                    }
                }//if
                set.add(c);
            }
            if (isTrue) cnt++;
        }
        System.out.println(cnt);
    }
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 매일 풀기 19일차] 1202]]></title>
            <link>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-19%EC%9D%BC%EC%B0%A8-1202</link>
            <guid>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-19%EC%9D%BC%EC%B0%A8-1202</guid>
            <pubDate>Tue, 02 Dec 2025 05:52:28 GMT</pubDate>
            <description><![CDATA[<h2 id="백준-11866-요세푸스-문제-0">[백준 11866 요세푸스 문제 0]</h2>
<blockquote>
<h3 id="아이디어">아이디어</h3>
</blockquote>
<p>👿 *<em>핵심 파악 *</em>
    - 한줄 요약: 원형으로 앉은 N명에서 K번째마다 제거해 순서 구하기 
    - 입력: N(사람 수), K(제거 간격)
    - 출력: 제거된 순서 &lt;a, b, c, ...&gt; 형식</p>
<p>🧻 *<em>문제 분류 *</em></p>
<ul>
<li>알고리즘: 구현, 큐 회전 </li>
<li>자료구조: Queue(ArrayDeque) </li>
<li>시간 복잡도: O(n*k) -&gt; N명 제거해 각각 k-1번 회전 </li>
</ul>
<p>💡*<em>아이디어 및 의사코드 *</em> </p>
<pre><code>Queue에 1~N 넣기 

반복 ( 큐가 빌때까지 ) : 
    //K-1명을 앞에서 빼서 뒤로 보내기 
    K-1번 반복: 
        poll()하고 offer() 
    //K번째 사람 제거 
    poll()해서 결과에 추가 </code></pre><p>✅ <strong>예외상황</strong> </p>
<ul>
<li>마지막 원소 쉼표 처리 </li>
</ul>
<hr>
<pre><code class="language-java">package boj_silver.p11866_요세푸스;

import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        //이중 연결 리스트로 해야하나? -&gt; 결국 생각 못함 -&gt;  원형 큐는 poll()하고 offer()하는 연산
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = sc.nextInt();
        StringBuilder sb =  new StringBuilder();

        //Queue에 1~N 넣기
        Queue&lt;Integer&gt; q = new ArrayDeque&lt;&gt;();
        for (int i = 1; i&lt;=n; i++){
            q.offer(i);
        }// N = 7일때 q = {1,2,3,4,5,6,7}

        sb.append(&quot;&lt;&quot;);

        while(!q.isEmpty()){
            //k-1명을 앞에서 뒤로 보내기
            for (int i =0; i&lt; k-1; i++){
                q.offer(q.poll());
            }
            sb.append(q.poll());
            //마지막이 아니면 , 추가
            if(!q.isEmpty()){
                sb.append(&quot;, &quot;);
            }
        }
        sb.append(&quot;&gt;&quot;);
        System.out.println(sb);

        sc.close();

    }
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 매일 풀기 18일차] 1201]]></title>
            <link>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-18%EC%9D%BC%EC%B0%A8-1201</link>
            <guid>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-18%EC%9D%BC%EC%B0%A8-1201</guid>
            <pubDate>Tue, 02 Dec 2025 04:42:50 GMT</pubDate>
            <description><![CDATA[<h2 id="백준-4179-불"><a href="https://www.acmicpc.net/problem/4179">백준 4179 불</a></h2>
<p>소요시간 : 90분..</p>
<blockquote>
<p> <strong>아이디어</strong> </p>
</blockquote>
<ul>
<li><p><strong>핵심</strong> : 지훈이가 불보다 먼저 움직여서 가장 자리로 탈출 가능한가? </p>
</li>
<li><p><strong>문제 분류</strong>
a. 최단 거리 / 시간 -&gt; bfs 알고리즘 
b. 불과 사람이 동시에 이동 -&gt; 멀티 bfs</p>
</li>
<li><p>*<em>알고리즘 설계 *</em>
```</p>
</li>
</ul>
<ol>
<li>입력 받기 </li>
</ol>
<ul>
<li>지도 입력하며, J, F 위치 저장 </li>
<li>fireTime, exitTime 배열 -1로 초기화 </li>
</ul>
<ol start="2">
<li>불 BFS 실행 </li>
</ol>
<ul>
<li>모든 F 위치 큐에 넣고 시작 </li>
<li>4방향 탐색하며, fireTime[nx][ny] 갱신 </li>
<li>벽(#)은 지나갈 수 없음 </li>
</ul>
<ol start="3">
<li>지훈 bfs 실행 </li>
</ol>
<ul>
<li>J위치에서 시작 </li>
<li>4 방향 탐색하며: 
  a. 범위 벗어나면 탈출 성공 -&gt; 시간 출력하고 종료 
  b. 벽이거나 이미 방문 -&gt; continue
  c. 불이 먼저 도착 -&gt; contonue 
  d. 갈 수 있으면 큐에 추가 </li>
<li>큐가 비면 -&gt; IMPOSSIBLE </li>
</ul>
<ol start="4">
<li>출력 </li>
</ol>
<h2 id="">``</h2>
<pre><code class="language-java">package boj_gold.p4179_불;

//미로 문제 이구만
// 경계 설정이 잘 되야겠구만
// 아이디어: 불과 지훈이의 bfs 모두 돌려얗.ㅁ
// 불의 bfs를 먼저 돌려야함 ( 지훈이의 이동에 영향 안받음)
// 각칸에 불이 전파되는 시간을 구한다.
// 지훈이의 bfs를 돌려 이동시킨다.
    // 지훈이보다 먼저 불이 도달한 공간에는 방문할 수 없다.
    // 불이 특정 공간에 도달하는 시간 &lt;= 지훈이가 특정 공간에 도달하는 시간
// 지훈이가 배열의 범위를 벗어나면, 탈출 성공
// 배열의 범위 못벗어나면, 탈출 실패 -&gt; impossible 출력

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Answer {
    static int n, m;
    static char[][] maps;

    static int[][] fireTime; //불이 각 칸에 도달하는 시간
    static int[][] exitTime; //지훈이가 도달하는 시간


    static Queue&lt;int[]&gt; q1;
    static Queue&lt;int[]&gt; q2;

    static boolean[][] visited;
    static int[] dx = {-1, 1, 0, 0};
    static int[] dy = {0, 0, -1, 1};

    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());
        fireTime = new int[n][m];
        exitTime = new int[n][m];
        q1 = new LinkedList&lt;&gt;();
        q2 = new LinkedList&lt;&gt;();

        maps = new char[n][m];


        //입력 받기 #은 0으로 생각, J는 이동 F는 불이어서 bfs로 퍼짐 // 만약 탈출되지 않으면 Impossible 출력
        // . 은  1로 생각
        for (int i = 0; i &lt; n; i++) {
            String line = br.readLine();
            for (int j = 0; j &lt; m; j++) {
                maps[i][j] = line.charAt(j);
                //시간 초기화 하기
                fireTime[i][j] = -1;
                exitTime[i][j] = -1;
                //불 인덱스 추가
                if (maps[i][j] == &#39;F&#39;) {
                    //불의 인덱스 추가
                    q1.offer(new int[]{i, j});
                    fireTime[i][j] = 0; //불 시작점은 시간 0
                } else if (maps[i][j] == &#39;J&#39;) {
                    q2.offer(new int[]{i, j});
                    exitTime[i][j] = 0; //초기화
                }
            }
        }//입력 받기

        // 불에 대한 bfs
        while (!q1.isEmpty()) {
            int[] cur = q1.poll();
            int x = cur[0];
            int y = cur[1];
            for (int i = 0; i &lt; 4; i++) {
                int nx = x + dx[i];
                int ny = y + dy[i];
                // 경계 벗어나면 x
                if (nx &lt; 0 || nx &gt;= n || ny &lt; 0 || ny &gt;= m) continue;
                //불이 먼저 오면 안됨
                if (fireTime[nx][ny] &gt;= 0 || maps[nx][ny] == &#39;#&#39;) continue;
                fireTime[nx][ny] = fireTime[x][y] + 1;
                q1.offer(new int[]{nx, ny});
            }
        }
        //지훈이 bfs
        while (!q2.isEmpty()) {
            int[] cur = q2.poll();
            int x = cur[0];
            int y = cur[1];
            for (int i = 0; i &lt; 4; i++) {
                int nx = x + dx[i];
                int ny = y + dy[i];
                //범위 벗어나면 탈출
                if (nx &lt; 0 || nx &gt;= n || ny &lt; 0 || ny &gt;= m) {
                    System.out.println(exitTime[x][y] + 1);
                    return;
                }
                if (exitTime[nx][ny] &gt;= 0 || maps[nx][ny] == &#39;#&#39;) continue;
                //불의 전파 시간이 더 먼저 오면
                // 불이 오는 칸이면 비교 fireTime == -1이면 불이 안오는 칸 -&gt; 안전

                if (fireTime[nx][ny]!= -1 &amp;&amp; fireTime[nx][ny] &lt;= exitTime[x][y] + 1) continue;
                exitTime[nx][ny] = exitTime[x][y] + 1;
                q2.offer(new int[]{nx, ny});
            }
        }
        System.out.println(&quot;IMPOSSIBLE&quot;);

    }//main


}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring MVC 1편] Sec4. Servlet, JSP, MVC 패턴 ]]></title>
            <link>https://velog.io/@haing3_3/Spring-MVC-1%ED%8E%B8-Sec4.-Servlet-JSP-MVC-%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@haing3_3/Spring-MVC-1%ED%8E%B8-Sec4.-Servlet-JSP-MVC-%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Thu, 27 Nov 2025 04:58:16 GMT</pubDate>
            <description><![CDATA[<h1 id="1-회원-관리-웹-애플리케이션-요구사항">1. 회원 관리 웹 애플리케이션 요구사항</h1>
<h2 id="핵심-기능">핵심 기능</h2>
<ul>
<li><strong>회원 저장</strong></li>
<li><strong>회원 목록 조회</strong></li>
</ul>
<h2 id="회원-정보-domain-model">회원 정보 (Domain Model)</h2>
<ul>
<li>이름 (<code>username</code>)</li>
<li>나이 (<code>age</code>)</li>
<li>도메인 객체: <code>Member</code></li>
<li>저장소: <code>MemberRepository</code> (메모리 저장소)</li>
</ul>
<h2 id="저장소-요구사항">저장소 요구사항</h2>
<ul>
<li><p><strong>싱글톤 패턴 적용</strong></p>
<ul>
<li>순수 서블릿 환경에서는 스프링이 없으므로 직접 싱글톤 생성</li>
<li><code>private static final MemberRepository instance = new MemberRepository();</code></li>
<li><code>public static MemberRepository getInstance()</code></li>
</ul>
</li>
</ul>
<h2 id="테스트-코드">테스트 코드</h2>
<ul>
<li>저장소는 메모리 기반이므로 테스트 간 영향 제외 필요</li>
<li>테스트 종료 후 store 초기화</li>
</ul>
<pre><code class="language-java">@AfterEach
void afterEach() {
    memberRepository.clearStore();
}</code></pre>
<hr>
<h1 id="2-servlet-기반-회원-관리-웹-애플리케이션">2. Servlet 기반 회원 관리 웹 애플리케이션</h1>
<p>Servlet으로 직접 HTML을 생성하며 웹 기능 구현.</p>
<h2 id="2-1-회원-등록-폼-제공-memberformservlet">2-1. 회원 등록 폼 제공 (MemberFormServlet)</h2>
<ul>
<li>사용자에게 <code>&lt;form&gt;</code> 페이지 제공</li>
<li>단순히 JSP 없이 HTML 문자열을 직접 만들어 응답</li>
</ul>
<h2 id="2-2-회원-저장-membersaveservlet">2-2. 회원 저장 (MemberSaveServlet)</h2>
<ul>
<li>HttpServletRequest에서 파라미터 조회
<code>String username = request.getParameter(&quot;username&quot;)</code></li>
<li>Member 객체 생성 → <code>memberRepository.save(member)</code></li>
<li>HTML 응답을 <strong>직접 문자열로 작성</strong>해 동적으로 출력</li>
</ul>
<p>→ <strong>HTML을 자바 코드로 직접 작성해야 해서 유지보수 매우 어려움</strong></p>
<h2 id="2-3-회원-목록-조회-memberlistservlet">2-3. 회원 목록 조회 (MemberListServlet)</h2>
<ul>
<li><code>List&lt;Member&gt; members = memberRepository.findAll()</code></li>
<li>반복문(for)을 돌면서 HTML 테이블을 자바 코드로 생성</li>
</ul>
<hr>
<h2 id="템플릿-엔진-등장-배경">템플릿 엔진 등장 배경</h2>
<p>Servlet은 HTML과 Java 코드가 섞여 복잡하고 유지보수성이 떨어짐.</p>
<p>→ HTML은 HTML대로, 동적 데이터는 템플릿 엔진에서 바꾸도록 개선</p>
<ul>
<li>JSP, Thymeleaf, Freemarker 등 등장</li>
<li>스프링 MVC에서는 JSP보다 Thymeleaf를 더 권장</li>
</ul>
<hr>
<h1 id="3-jsp로-회원-관리-웹-애플리케이션-구현">3. JSP로 회원 관리 웹 애플리케이션 구현</h1>
<p>JSP는 HTML 중심이며, 필요한 부분만 Java 코드로 삽입 가능.</p>
<h3 id="기본-문법">기본 문법</h3>
<ul>
<li>JSP 파일 선언
<code>&lt;%@ page contentType=&quot;text/html;charset=UTF-8&quot; language=&quot;java&quot; %&gt;</code></li>
<li>import
<code>&lt;%@ page import=&quot;hello.servlet.domain.member.MemberRepository&quot; %&gt;</code></li>
<li>자바 코드 삽입
<code>&lt;% ... %&gt;</code></li>
<li>값 출력
<code>&lt;%= member.getUsername() %&gt;</code></li>
</ul>
<p>JSP를 통해 <strong>HTML 중심 코드 작성 + 필요한 곳만 Java 삽입</strong>이 가능해짐.</p>
<p>하지만 JSP도 여전히 문제:</p>
<ul>
<li>JSP 안에 비즈니스 로직이 섞임</li>
<li>Repository 접근 코드가 그대로 노출</li>
<li>유지보수 어려움</li>
</ul>
<hr>
<h1 id="4-servlet--jsp로-mvc-패턴-도입">4. Servlet + JSP로 MVC 패턴 도입</h1>
<p>비즈니스 로직과 화면 렌더링을 분리하기 위한 구조가 <strong>MVC 패턴</strong></p>
<hr>
<h2 id="4-1-mvc-구조">4-1. MVC 구조</h2>
<h3 id="model">Model</h3>
<ul>
<li>화면(View)에 전달할 데이터를 담는 역할</li>
<li>Servlet에서는 <code>request.setAttribute(&quot;key&quot;, value)</code> 사용</li>
</ul>
<h3 id="view">View</h3>
<ul>
<li>JSP</li>
<li>HTML 출력에 집중</li>
<li>JSP에서는 <code>${}</code> EL 문법 제공</li>
</ul>
<h3 id="controller">Controller</h3>
<ul>
<li>HttpServletRequest/Response 사용</li>
<li>비즈니스 로직 호출, 결과를 Model에 담아 View로 전달</li>
<li>View 호출: <code>request.getRequestDispatcher(viewPath).forward(req, resp)</code></li>
</ul>
<hr>
<h2 id="4-2-mvc에서-redirect와-forward-차이">4-2. MVC에서 redirect와 forward 차이</h2>
<h3 id="forward">Forward</h3>
<ul>
<li>서버 내부에서 JSP 또는 다른 Servlet을 호출</li>
<li>브라우저 주소창 URL <strong>변경 없음</strong></li>
</ul>
<h3 id="redirect">Redirect</h3>
<ul>
<li>브라우저에게 다시 요청하라고 응답</li>
<li>주소창 URL <strong>변경됨</strong></li>
<li>POST-Redirect-GET 패턴에 자주 사용</li>
</ul>
<hr>
<h1 id="5-mvc-패턴-구현-핵심-흐름">5. MVC 패턴 구현 핵심 흐름</h1>
<h2 id="5-1-등록-폼-controller">5-1. 등록 폼 Controller</h2>
<ul>
<li><code>/WEB-INF/views/new-form.jsp</code> 호출</li>
<li><code>WEB-INF</code> 내부 파일은 외부 URL 직접 접근 불가 → Controller를 반드시 거쳐야 함</li>
</ul>
<h2 id="5-2-회원-저장-controller">5-2. 회원 저장 Controller</h2>
<ul>
<li>폼 데이터 조회</li>
<li>Member 저장</li>
<li>request.setAttribute()로 View에 데이터 전달</li>
<li>결과 JSP forward</li>
</ul>
<h2 id="5-3-회원-목록-controller">5-3. 회원 목록 Controller</h2>
<ul>
<li><code>List&lt;Member&gt;</code> 조회 후 request에 저장</li>
<li>JSP에서 JSTL <code>&lt;c:forEach&gt;</code> 로 반복 렌더링</li>
</ul>
<p>JSTL 예:</p>
<pre><code class="language-jsp">&lt;c:forEach var=&quot;item&quot; items=&quot;${members}&quot;&gt;
    &lt;tr&gt;
        &lt;td&gt;${item.id}&lt;/td&gt;
        &lt;td&gt;${item.username}&lt;/td&gt;
        &lt;td&gt;${item.age}&lt;/td&gt;
    &lt;/tr&gt;
&lt;/c:forEach&gt;</code></pre>
<hr>
<h1 id="6-mvc-패턴의-한계">6. MVC 패턴의 한계</h1>
<p>컨트롤러와 뷰는 분리되었지만 여전히 다음 문제가 존재함.</p>
<h3 id="1-view-호출-코드-중복">1) View 호출 코드 중복</h3>
<ul>
<li><code>dispatcher.forward()</code> 반복</li>
<li>viewPath 반복
<code>/WEB-INF/views/</code> + viewName + <code>.jsp</code></li>
</ul>
<h3 id="2-httpservletrequestresponse-의존">2) HttpServletRequest/Response 의존</h3>
<ul>
<li>컨트롤러가 서블릿 API에 강하게 결합됨</li>
<li>테스트 코드 작성 어려움</li>
</ul>
<h3 id="3-공통-로직-처리-어려움">3) 공통 로직 처리 어려움</h3>
<ul>
<li>각 컨트롤러마다 중복되는 로직(로그, 인증, 예외 처리 등) 존재</li>
<li>이를 공통 처리하려면 별도 도구 필요</li>
</ul>
<hr>
<h2 id="7-front-controller-패턴-mvc-프레임워크의-핵심">7. Front Controller 패턴 (MVC 프레임워크의 핵심)</h2>
<p>위 문제를 해결하기 위해 등장한 패턴.</p>
<ul>
<li><strong>모든 요청은 FrontController(Servlet) 한 곳으로 들어온다</strong></li>
<li>공통 로직은 FrontController에서 처리</li>
<li>실제 비즈니스 처리는 각 컨트롤러로 위임</li>
<li>스프링 MVC의 DispatcherServlet이 이 패턴 기반</li>
</ul>
<p>→ 이를 기반으로 하면 우리가 <strong>직접 작은 MVC 프레임워크를 만들 수도 있다.</strong></p>
<hr>
<h1 id="✨-핵심-요약">✨ 핵심 요약</h1>
<ol>
<li>Servlet만 사용하면 HTML을 Java 코드로 생성해야 하므로 유지보수 최악</li>
<li>JSP 도입 → HTML 중심 코딩 가능해졌지만 비즈니스 로직 섞이는 문제 존재</li>
<li>MVC 패턴 → Controller, View, Model 분리</li>
<li>하지만 MVC 구조에서도 forward/viewPath 중복, 공통 기능 처리 어려움</li>
<li>Front Controller(DispatcherServlet)로 모든 문제 해결
→ 스프링 MVC는 이를 기반으로 만든 완성형 구조</li>
</ol>
<hr>
<h3 id="출처">출처</h3>
<blockquote>
</blockquote>
<ul>
<li><a href="https://www.inflearn.com/courses/lecture?courseId=326674&amp;type=LECTURE&amp;unitId=71178&amp;subtitleLanguage=ko">김영한의 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 매일 풀기 17일차] 1127]]></title>
            <link>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-17%EC%9D%BC%EC%B0%A8-1127</link>
            <guid>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-17%EC%9D%BC%EC%B0%A8-1127</guid>
            <pubDate>Thu, 27 Nov 2025 00:59:17 GMT</pubDate>
            <description><![CDATA[<h2 id="백준-15649-n과m1"><a href="https://www.acmicpc.net/problem/15649">백준 15649 N과M(1)</a></h2>
<blockquote>
<p><strong>중복 없는 순열</strong> </p>
</blockquote>
<ul>
<li>index를 기준으로 인덱스가 m이 되는 순간 출력한다. </li>
<li>선택할 배열에 숫자를 넣으면서 index+1을 담은 변수로 재귀 호출을 한 뒤, boolean 배열을 다시 false로 백트래킹한다. </li>
</ul>
<pre><code class="language-java">import java.util.Scanner;

public class Main {
    static boolean[] isSelected;
    static int[] select;
    static int n, m ;
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //1부터 n까지 중복없이 m개를 고른 수열
        //n = 3, m = 2
        n = scan.nextInt();
        m = scan.nextInt();
        select = new int[m];
        isSelected = new boolean[n];


        combi(0);//index
    }
    static void combi(int index){
        StringBuilder sb = new StringBuilder();
        if (index&gt;=m){
            //출력
            for (int i = 0; i&lt;m; i++){
                sb.append(select[i]).append(&quot; &quot;);
            }
            System.out.println(sb);
            return;
        }

        for (int i=0; i&lt;n; i++){
            if(!isSelected[i]){
                //select[index]
                select[index] = i+1;
                isSelected[i] = true;
                combi(index+1);
                isSelected[i] = false;
            }
        }


    }
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 매일 풀기 16일차] 1126]]></title>
            <link>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-16%EC%9D%BC%EC%B0%A8-1126</link>
            <guid>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-16%EC%9D%BC%EC%B0%A8-1126</guid>
            <pubDate>Thu, 27 Nov 2025 00:54:49 GMT</pubDate>
            <description><![CDATA[<h2 id="백준-1417-국회의원-선거"><a href="https://www.acmicpc.net/problem/1417">백준 1417 국회의원 선거</a></h2>
<blockquote>
<p><strong>아이디어</strong></p>
</blockquote>
<ul>
<li>다솜밖에 없는 경우 출력 </li>
<li>다솜 제외하고, 정렬한후 마지막 인덱스부터 비교하면서, 1표씩 가져오기 (다솜이가 많을때 break문으로 빠져나옴) </li>
</ul>
<pre><code class="language-java">import java.util.Arrays;
import java.util.Scanner;

public class Main {
    //배열에 저장하자
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n= scan.nextInt();

        int som = scan.nextInt();
        if(n==1){
            System.out.println(0);
            return;
        }

        int[] candi = new int[n-1];

        for (int i = 0; i &lt;n-1; i++) {
            candi[i] = scan.nextInt(); //1번이 많아야함. 그럼 일단 정렬해보고.
        }
        int cnt =0;
        //비교해서 정렬해야하나
        while(true){
            //다솜이 1등 될때까지 반복
            Arrays.sort(candi);
            int maxIdx = n-2; //마지막 인덱스
            if (som &gt; candi[maxIdx]){
                break;
            }
            //가장 많이 득표한 후보 1표 가져오기
            candi[maxIdx]--;
            som++;
            cnt++;
        }
        System.out.println(cnt);


    }
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring MVC 1편] Sec3. Servlet ]]></title>
            <link>https://velog.io/@haing3_3/Spring-MVC-1%ED%8E%B8-Sec3.-Servlet</link>
            <guid>https://velog.io/@haing3_3/Spring-MVC-1%ED%8E%B8-Sec3.-Servlet</guid>
            <pubDate>Wed, 26 Nov 2025 06:38:25 GMT</pubDate>
            <description><![CDATA[<h1 id="11-hello-서블릿">11. Hello 서블릿</h1>
<p>스프링 부트 환경에서도 톰캣을 별도로 설치하지 않아도 서블릿을 사용할 수 있다.
스프링 부트는 <strong>내장 톰캣(Embedded Tomcat)</strong>을 내장하고 있기 때문이며,
서블릿을 등록하면 자동으로 서블릿 컨테이너가 초기화된다.</p>
<h2 id="111-스프링-부트-서블릿-환경-구성">11.1 스프링 부트 서블릿 환경 구성</h2>
<p><strong>@WebServlet</strong> 애노테이션을 통해 서블릿 등록 가능.</p>
<ul>
<li><strong>name</strong>: 서블릿 이름</li>
<li><strong>urlPatterns</strong>: 어떤 URL을 서블릿과 매핑할지 결정</li>
</ul>
<p>예시:</p>
<pre><code class="language-java">@WebServlet(name = &quot;helloServlet&quot;, urlPatterns = &quot;/hello&quot;)
public class HelloServlet extends HttpServlet { ... }</code></pre>
<p>Spring Boot는 <strong>@ServletComponentScan</strong>이 붙은 패키지에서 @WebServlet 등을 자동 스캔해준다.</p>
<h3 id="httpservletrequest-활용">HttpServletRequest 활용</h3>
<pre><code class="language-java">String username = request.getParameter(&quot;username&quot;);</code></pre>
<p>→ GET 쿼리 파라미터, POST form 모두 이 방식으로 조회 가능.</p>
<h3 id="톰캣-내부-요청-로그-보기">톰캣 내부 요청 로그 보기</h3>
<pre><code class="language-properties">logging.level.org.apache.coyote.http11=trace</code></pre>
<p>→ HTTP 요청/응답이 내부에서 어떻게 처리되는지 확인할 수 있다.</p>
<hr>
<h2 id="112-서블릿-컨테이너-동작-방식-핵심">11.2 서블릿 컨테이너 동작 방식 핵심</h2>
<ul>
<li><strong>WAS(톰캣)는 Http 요청이 오면 Request/Response 객체를 만들어 서블릿에게 전달한다.</strong></li>
<li>개발자는 서블릿 내부에서 요청 객체를 조회하면서 응답을 작성한다.</li>
<li>WAS는 서블릿이 만든 Response 내용을 바탕으로 HTTP 응답 메시지를 최종 조립하여 클라이언트에게 보낸다.</li>
</ul>
<p>즉, <strong>WAS는 HTTP 요청/응답 메시지를 대신 만들어주고</strong>,
서블릿은 그 안의 <strong>비즈니스 로직을 실행하는 코드</strong>이다.</p>
<hr>
<h2 id="113-welcome-페이지-추가">11.3 welcome 페이지 추가</h2>
<p>static 폴더에 <code>index.html</code>을 두면 자동으로 welcome 페이지로 매핑된다.</p>
<hr>
<h1 id="12-httpservletrequest">12. HttpServletRequest</h1>
<h2 id="121-역할">12.1 역할</h2>
<p>HTTP 메시지를 개발자가 직접 파싱하지 않도록
서블릿 컨테이너가 <strong>HTTP 요청 메시지를 해석하여</strong>
start-line, header, body 정보를 <strong>HttpServletRequest 객체에 담아 제공</strong>한다.</p>
<p>즉, <strong>HTTP 스펙을 더 쉽게 사용하도록 만들어주는 추상화 계층</strong>이다.</p>
<hr>
<h2 id="122-http-요청-메서드-예시">12.2 Http 요청 메서드 예시</h2>
<pre><code>POST /save HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded

username=kim&amp;age=20</code></pre><p>request 객체는 다음과 같은 정보 조회를 지원한다.</p>
<ul>
<li><code>request.getMethod()</code></li>
<li><code>request.getRequestURL()</code>, <code>getRequestURI()</code></li>
<li><code>request.getHeader(&quot;Host&quot;)</code></li>
<li><code>request.getParameter(&quot;username&quot;)</code></li>
</ul>
<hr>
<h3 id="부가기능--임시-저장소">부가기능 – 임시 저장소</h3>
<p><strong>요청 단위로 유지되는 저장소 기능</strong></p>
<pre><code class="language-java">request.setAttribute(&quot;key&quot;, value);
request.getAttribute(&quot;key&quot;);</code></pre>
<p>Filter → Controller 등 여러 계층에서 데이터를 공유할 때 유용하다.</p>
<hr>
<h3 id="세션-관리-기능">세션 관리 기능</h3>
<p><code>request.getSession()</code>을 통해 세션 생성/조회 가능
→ 로그인, 장바구니 등 사용자 상태 유지에 사용</p>
<hr>
<h3 id="핵심">핵심</h3>
<blockquote>
<p><strong>HttpServletRequest와 HttpServletResponse는 HTTP 메시지를 다루기 쉽게 도와주는 도구일 뿐이다.</strong>
따라서 <strong>HTTP 메시지 구조(start-line, header, body)를 정확히 이해하는 것</strong>이 더 중요하다.</p>
</blockquote>
<hr>
<h2 id="123-기본-사용법-확인">12.3 기본 사용법 확인</h2>
<p>요청 라인(start-line) 및 header를 읽는 예:</p>
<pre><code>request.getMethod() = GET
request.getProtocol() = HTTP/1.1
request.getRequestURL() = http://localhost:8080/request-header
request.getRequestURI() = /request-header
request.getQueryString() = null
request.isSecure() = false</code></pre><hr>
<h2 id="http-요청-데이터-종류">HTTP 요청 데이터 종류</h2>
<p>서버로 데이터를 전달하는 방식은 3가지이다.</p>
<h3 id="1-get--쿼리-파라미터">1) GET – 쿼리 파라미터</h3>
<ul>
<li>URL 뒤에 <code>?username=hello&amp;age=20</code></li>
<li>message body 없음</li>
<li>검색, 필터링에 자주 사용</li>
</ul>
<h3 id="2-post--html-form">2) POST – HTML Form</h3>
<ul>
<li>Content-Type: <code>application/x-www-form-urlencoded</code></li>
<li>message body 안에 <code>key=value&amp;key2=value2</code> 형태</li>
<li>회원가입, 로그인 등 form 기반 요청</li>
</ul>
<h3 id="3-http-message-bodyraw-body">3) HTTP Message Body(raw body)</h3>
<ul>
<li>JSON, XML, text 등</li>
<li>Content-Type: <code>application/json</code> 등</li>
<li>API 서버에서 가장 많이 쓰는 방식</li>
</ul>
<hr>
<h1 id="19-httpservletresponse">19. HttpServletResponse</h1>
<h2 id="191-기본-사용법">19.1 기본 사용법</h2>
<p>서버가 클라이언트에게 <strong>HTTP 응답 메시지를 작성해서 보내는 객체</strong></p>
<h3 id="http-응답-메시지-구성-요소">HTTP 응답 메시지 구성 요소</h3>
<ol>
<li><p><strong>status line</strong></p>
<ul>
<li><code>response.setStatus(200)</code></li>
</ul>
</li>
<li><p><strong>header</strong></p>
<ul>
<li><code>response.setHeader(&quot;Content-Type&quot;, &quot;text/plain&quot;)</code></li>
</ul>
</li>
<li><p><strong>body</strong></p>
<ul>
<li><code>response.getWriter().write(&quot;ok&quot;)</code></li>
</ul>
</li>
</ol>
<hr>
<h2 id="편의-기능">편의 기능</h2>
<ul>
<li>Content-Type 지정
<code>response.setContentType(&quot;text/html&quot;)</code></li>
<li>Character Encoding
<code>response.setCharacterEncoding(&quot;utf-8&quot;)</code></li>
<li>쿠키 생성
<code>response.addCookie(cookie)</code></li>
<li>리다이렉트
<code>response.sendRedirect(&quot;/new-url&quot;)</code></li>
</ul>
<hr>
<h2 id="192-http-응답-데이터-형태">19.2 Http 응답 데이터 형태</h2>
<h3 id="1-단순-텍스트">1) 단순 텍스트</h3>
<pre><code class="language-java">response.getWriter().write(&quot;Hello&quot;);</code></pre>
<h3 id="2-html-응답">2) HTML 응답</h3>
<pre><code class="language-java">response.setContentType(&quot;text/html&quot;);
response.getWriter().write(&quot;&lt;html&gt;...&lt;/html&gt;&quot;);</code></pre>
<h3 id="3-json-응답">3) JSON 응답</h3>
<pre><code class="language-java">response.setContentType(&quot;application/json&quot;);
response.getWriter().write(objectMapper.writeValueAsString(obj));</code></pre>
<p>※ <code>application/json</code>은 charset 파라미터를 지원하지 않으므로,
문자 인코딩은 response의 CharacterEncoding으로 지정한다.</p>
<hr>
<h1 id="✨-서블릿-핵심-요약">✨ 서블릿 핵심 요약</h1>
<ol>
<li><p><strong>서블릿은 WAS 내부에서 실행되는 자바 클래스</strong>
→ HTTP 요청/응답을 처리하기 위한 기반 기술</p>
</li>
<li><p><strong>HttpServletRequest는 HTTP 요청 메시지를 자동으로 파싱하여 제공</strong>
→ 쿼리 파라미터, header, body, 세션 등</p>
</li>
<li><p><strong>HttpServletResponse는 HTTP 응답 메시지를 쉽게 생성하도록 도와줌</strong></p>
</li>
<li><p><strong>GET/POST 차이의 본질은 데이터 전달 위치 (URL vs Body)</strong></p>
</li>
<li><p><strong>JSON 기반 API는 Message Body를 직접 읽고 객체로 변환하여 사용</strong></p>
</li>
</ol>
<hr>
<h3 id="출처">출처</h3>
<blockquote>
</blockquote>
<ul>
<li><a href="https://www.inflearn.com/courses/lecture?courseId=326674&amp;type=LECTURE&amp;unitId=71178&amp;subtitleLanguage=ko">김영한의 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술</a></li>
<li><a href="https://sigridjin.medium.com/servletcontainer%EC%99%80-springcontainer%EB%8A%94-%EB%AC%B4%EC%97%87%EC%9D%B4-%EB%8B%A4%EB%A5%B8%EA%B0%80-626d27a80fe5">ServletContainer와 SpringContainer는 무엇이 다른가?</a>
Controller 1개는 어떻게 수십 만개의 요청을 처리하는가 </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 매일 풀기 15일차] 1125]]></title>
            <link>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-15%EC%9D%BC%EC%B0%A8-1125</link>
            <guid>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-15%EC%9D%BC%EC%B0%A8-1125</guid>
            <pubDate>Tue, 25 Nov 2025 10:39:33 GMT</pubDate>
            <description><![CDATA[<h2 id="백준-10282-해킹"><a href="https://www.acmicpc.net/problem/10282">백준 10282 해킹</a></h2>
<blockquote>
<p><strong>아이디어</strong> </p>
</blockquote>
<ul>
<li>입력 : 테스트 케이스 T만큼 반복하고, n: 컴퓨터 개수 / d: 간선개수 / c: 시작 번호 </li>
<li>자료 구조 ArrayList<Node>[] list로 각 1부터..n까지의 list 초기화 시켜야함 ! </li>
<li>간선 입력 </li>
<li>dist거리 선언하고, max_value로 초기화 -&gt;dist[c] =0으로 초기화 </li>
<li>PriorityQueue<Node> pq 선언하고 오름차순 정렬 
pq.offer(new Node(c, 0));//거리 w를 0으로 초기화 </li>
<li><pre><code>//while(큐가 빌때까지): 
    Node cur = pq.poll()l; //현재 노드 빼내오기
    int curV = cur.v; //현재 정점
    int curD = cur.w; //현재 거리 
//이미 처리된 노드이면 continue 
//현재 노드와 연결된 간선 탐색 
    //누적 거리 
    // 더 짧은 노드 발견하면 갱신하고, 새로운 노드 큐에 넣기 </code></pre></li>
</ul>
<p>  코드 </p>
<pre><code class="language-java">package boj_gold.p10282_해킹;


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

class Node{
    int v;
    int w;

    public Node(int v, int w){
        this.v = v;
        this.w =w;
    }
}
public class Main {
    static int[] dist;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        int T = Integer.parseInt(st.nextToken());
        StringBuilder sb = new StringBuilder();

        for(int i = 0; i &lt; T; i++){
            st = new StringTokenizer(br.readLine());
            int n = Integer.parseInt(st.nextToken());// 컴퓨터 개수
            int d = Integer.parseInt(st.nextToken()); //간선 개수
            int c =  Integer.parseInt(st.nextToken()); //시작 번호

            ArrayList&lt;Node&gt;[] list = new ArrayList[n+1];
            //그래프 초기화
            for (int j= 1; j&lt;=n; j++){
                list[j] = new ArrayList&lt;&gt;();
            }
            //간선 입력
            for (int j = 0; j&lt; d; j++){
                st = new StringTokenizer(br.readLine());
                int v = Integer.parseInt(st.nextToken());
                int u = Integer.parseInt(st.nextToken());
                int w = Integer.parseInt(st.nextToken());
                list[u].add(new Node(v,w));
            }

            // 입력받기
            //각 dist초기화하기
            dist = new int[n+1];
            Arrays.fill(dist, Integer.MAX_VALUE);  //dist 초기화한후 min으로 업데이트 한다.
            //처음 값 초기화
            dist[c] = 0;

            //prioirty Queue로 가중치 오름추순 정렬
            PriorityQueue&lt;Node&gt; pq = new PriorityQueue&lt;&gt;((a,b)-&gt; a.w-b.w);
            pq.offer(new Node(c, 0)); //거리를 0으로 초기화

            //pq가 빌때까지 반복
            while(!pq.isEmpty()){
                //큐
                Node cur = pq.poll();
                int curV = cur.v; //현재 정점
                int curD = cur.w; //현재 거리

                //이미 처리된 노드이면 continue
                if (curD &gt; dist[curV]){
                    continue;
                }
                //현재 노드와 연결된 간선 탐색
                for (Node next: list[curV]){
                    int nextV = next.v;
                    int nextD = curD + next.w; //누적 거리

                    //더 짧은 노드 발견하면 갱신
                    if(nextD &lt; dist[nextV]){
                        dist[nextV] = nextD;
                        pq.offer(new Node(nextV, nextD));
                    }
                }
            }//while
            //출력을 해야하는데: 감염된 컴퓨터 수와 마지막 감염 시간
            int cnt= 0;
            int time = 0; //마지막 감염 시간

            for (int j = 1; j &lt;=n; j++){
                //dist가 업데이트가 된 것
                if (dist[j] != Integer.MAX_VALUE){
                    cnt++;
                    time = Math.max(time, dist[j]);
                }
            }//for
            sb.append(cnt).append(&quot; &quot;).append(time).append(&quot;\n&quot;);




         }//for 
        System.out.println(sb);


    }
}

</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 매일 풀기 14일차] 1124]]></title>
            <link>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-14%EC%9D%BC%EC%B0%A8-1124</link>
            <guid>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-14%EC%9D%BC%EC%B0%A8-1124</guid>
            <pubDate>Mon, 24 Nov 2025 05:34:37 GMT</pubDate>
            <description><![CDATA[<h2 id="백준-1753-최단경로"><a href="https://www.acmicpc.net/problem/1753">백준 1753 최단경로</a></h2>
<blockquote>
<p><strong>아이디어</strong> </p>
</blockquote>
<ul>
<li>간선을 저장하는 자료구조는 ArrayList[] list를 만들고, Edge class의 객체를 생성한다. </li>
<li>Edge 클래스는 도착점과 가중치가 저장된다. </li>
<li>dist[] 배열로 최소값 저장 
```</li>
</ul>
<ol>
<li>dist 배열 선언 및 초기화 (Max value로 초기화) </li>
<li>우선순위 큐 선언 (가중치 기준 오름차순) </li>
<li>시작점을 pq에 넣기 (시작점, 거리)</li>
<li>다익스트라 알고리즘 </li>
</ol>
<ul>
<li>while (pq가 빌때까지): 
  //pq에서 현재 노드 꺼내기 
  //이미 처리된 노드면 continue
  if(현재까지의 거리 &gt;  현재 거리) continue; 
  //현재 노드와 연결된 모든 간선 탐색 
  //더 짧으면 갱신 </li>
</ul>
<pre><code>



```java
    static int V, E, K;
    static ArrayList&lt;Edge&gt;[] graph; //전역 변수
    static StringBuilder sb;

    public static void main(String[] args) throws IOException{
        input();
        solution(K);

    }
    static void solution(int start){//bfs처럼 생각
        //1. 거리 배열 선언 및 초기화
        int[] dist = new int[V+1];
        //dist를 무한대로 초기화
        Arrays.fill(dist, Integer.MAX_VALUE);
        //dist[start] = 0
        dist[start] =0;

        //2. 우선순위 큐 선언( 가중치 기준 오름차순)
        PriorityQueue&lt;Edge&gt; pq = new PriorityQueue&lt;&gt;((a,b)-&gt; a.w- b.w);

        //시작점 pq에 넣기
        pq.offer(new Edge(start, 0)); //번호: start, 거리: 0

        //출력
        while(!pq.isEmpty()){
            Edge cur = pq.poll();
            int curN = cur.v; //현재 정점
            int curD = cur.w; //현재 거리
            //이미 처리된 노드이면 continue ( 더 짧은 경로로 이미 갱신)
            if (curD &gt; dist[curN]){
                continue;
            }
            //현재 노드와 연결된 간선 탐색
            for (Edge next: graph[curN]){
                int nextN = next.v;
                int nextD = curD + next.w;
                //더 짧은 경로 발견하면 갱신
                if(nextD &lt; dist[nextN]){
                    dist[nextN] = nextD;
                    pq.offer(new Edge(nextN, nextD));
                }

            }
        }//while
        //출력
        sb = new StringBuilder();
        for (int i = 1; i &lt;= V; i++){
            if(dist[i] ==Integer.MAX_VALUE){
                sb.append(&quot;INF\n&quot;);
            }else{
                sb.append(dist[i]).append(&quot;\n&quot;);
            }
        }
        System.out.println(sb);

    }</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 매일 풀기 13일차] 1121]]></title>
            <link>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-13%EC%9D%BC%EC%B0%A8-1121</link>
            <guid>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-13%EC%9D%BC%EC%B0%A8-1121</guid>
            <pubDate>Mon, 24 Nov 2025 01:09:34 GMT</pubDate>
            <description><![CDATA[<h2 id="백준-1654-랜선-자르기"><a href="https://www.acmicpc.net/problem/1654">백준 1654 랜선 자르기</a></h2>
<blockquote>
<p><strong>아이디어</strong> </p>
</blockquote>
<ul>
<li>처음에 이분탐색인지 모르겠음. </li>
<li>의사코드 <pre><code>left = 1, right = max(랜선들) 
while(left &lt;=right): 
  mid = (left+right) / 2
  if(mid로 잘랐을때 개수가 N이상이면): //길이를 늘려야함 
      answer = mid; //저장 
      left = mid+1; 
  else: 
      right= mid -1; </code></pre></li>
</ul>
<pre><code class="language-java">package boj_silver.p1654_랜선자르기;

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    static int ans;
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int k = scan.nextInt(); int n = scan.nextInt();
        //k개 입력 받기
        //랜선 길이가 최대 2^32 - 1이므로 long 사용
        long[] arr = new long[k];
        for (int i = 0; i &lt; k; i++) {
            arr[i] = scan.nextLong();
        }
        long left = 1;
        long right = 0;
        //최댓값
        for (int i = 0; i &lt; k; i++) {
            right = Math.max(right, arr[i]);
        }
        long ans = 0;

        while(left&lt;=right){
            long mid = (left+right)/ 2;
            //돌면서
            long sum = 0;
            for (int i = 0; i&lt; k; i++){
                sum += arr[i] / mid;
            }
            if(sum&gt;=n){
                ans = mid;
                left = mid+1;
            }else{
                right = mid-1;
            }
        }//while
        System.out.println(ans);

    }
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 매일 풀기 12일차] 1120 ]]></title>
            <link>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-12%EC%9D%BC%EC%B0%A8-1120</link>
            <guid>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-12%EC%9D%BC%EC%B0%A8-1120</guid>
            <pubDate>Fri, 21 Nov 2025 02:26:03 GMT</pubDate>
            <description><![CDATA[<h2 id="1--백준-2579-계단오르기">1.  <a href="https://www.acmicpc.net/problem/2579">백준 2579 계단오르기</a></h2>
<blockquote>
<p><strong>아이디어</strong> </p>
</blockquote>
<ul>
<li>dp[n]까지 점화식 만들고, dp[n]출력 </li>
<li>점화식: <code>dp[i] = Math.max(dp[i-3] + stairs[i-1] + stairs[i] , dp[i-2] + stairs[i]);</code></li>
</ul>
<pre><code class="language-java">package boj_silver.p2579_계단오르기;

import java.util.Scanner;

public class Review1 {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        int[] stairs = new int[n+1];
        for (int i = 1; i&lt;=n; i++){
            stairs[i] = scan.nextInt();
        }
        //dp 초기화
        int [] dp = new int[n+1];
        //만약 계단이 적다면 !
        dp[0] = 0;
        if (n&gt;=1){
            dp[1] = stairs[1];
        }
        if(n&gt;=2){
            dp[2] =  stairs[1] + stairs[2];
        }
        if (n&gt;=3){
            //dp 식
            for (int i = 3; i&lt;=n; i++){
                dp[i] = Math.max(dp[i-3] + stairs[i-1] + stairs[i], dp[i-2] + stairs[i]);
            }

        }
        System.out.println(dp[n]);


    }
}
</code></pre>
<h3 id="bottom-up-dp-내-방식-개선">Bottom-Up DP (내 방식 개선)</h3>
<pre><code class="language-java">int[] dp = new int[n+1]; 
dp[1] =stairs[1]; 
if(n&gt;=2) dp[2] = stairs[1] + stairs[2];
for (int i = 3; i&lt;=n;i++){
    dp[i] = Math.max(
        dp[i-2] + stairs[i], //2칸 점프 
        dp[i-3] + stairs[i-1] + stairs[i] //1칸씩 2번 
    );
}//for     </code></pre>
<p>*<em>일반적이고 이해하기 쉽다. 단점은 배열 사용으로 메모리가 O(n) *</em> </p>
<h3 id="top-down-dp-재귀--메모이제이션">Top-Down DP (재귀 + 메모이제이션)</h3>
<pre><code class="language-java">static Integer[] dp; //null 체크 위해 Integer 사용 
public static void main(String[] args) {
    dp[0]= 0; 
    dp[1] = stairs[1]; 
    if(n&gt;=2) dp[2]= stairs[1] + stairs[2]; 
    System.out.println(solve(n)); 
}//main

static int solve(int n){
    //이미 계산된것 건너뛰기 
    if(dp[n]!=null) return dp[n]; 

    dp[n]= Math.max(
        solve(n-2) + stairs[n], 
        solve(n-3)+ stairs[n-1] + stairs[n]
    ); 
    return dp[n]; 
}//solve: 재귀 </code></pre>
<h2 id="2-백준-1259-팰린드롬수">2. <a href="https://www.acmicpc.net/problem/1259">백준 1259 팰린드롬수</a></h2>
<blockquote>
<p><strong>아이디어</strong> </p>
</blockquote>
<ul>
<li>처음에는 queue로 해서 앞에 있는것과 peek를 비교해서 양 옆을 제거하고 싶었으나 마지막에 들어온 것 제거하는 방법 모름 =&gt; //Deque 사용하면 양쪽 삽입 삭제 가능 </li>
<li>그래서 그냥 배열로 받아 양쪽 비교하고, 안맞는 즉시 flag = false로 하고 바로 break함. <pre><code class="language-java">package boj_bronze.p1259_팰린드롬수;
</code></pre>
</li>
</ul>
<p>import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;</p>
<p>public class Main {
    public static void main(String[] args)throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        while(true){
            String str = br.readLine();
            //종료
            if(str.equals(&quot;0&quot;)){
                return;
            }
            //char로 바꾸기 !
            Character[] chars = new Character[str.length()];
            for (int i = 0; i &lt; str.length(); i++) {
                chars[i] = str.charAt(i);
            }
            int n = chars.length;
            boolean flag = true;</p>
<pre><code>        for(int i = 0; i&lt; n; i++){
            if (chars[i]  != chars[n-i-1]){
                //하는 순간 바로 flag = false
                flag = false;
                break;
            }
        }
        if(flag){
            System.out.println(&quot;yes&quot;);
        }else{
            System.out.println(&quot;no&quot;);
        }



    }//while 입력 받기


}</code></pre><p>}</p>
<pre><code>** 내방법의 시간 복잡도와 공간 복잡도는 O(n)이다. 투 포인터로 사용하면 공간 복잡도는 O(1)로 효율적으로 구현할 수 있다. 추가 메모리 없이 charAt()만 사용한다. 
```java
//main 메서드 
while(true){
    String str = br.readLine(); 
    if(str.equals(&quot;0&quot;)) break; //0들어오면 바로 입력 종료 

    //함수 적용해서 팰린드롬수가 맞으면, yes 아니면 no출력한다. 
    sb.append(isPalindrom(str) ? &quot;yes&quot; :&quot;no&quot;).append(&quot;\n&quot;);     
}//while 
//출력 
System.out.print(sb); 

//isPalindrom함수 
static boolean isPalindrome(String s){
    int l = 0; int r = s.length()-1; 

    while(l&lt;r){
        if(s.charAt(l++) !=s.charAt(r--)){
            return false; 
        }
    }//whie
    return true; 
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 매일 풀기 11일차] 1119]]></title>
            <link>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-11%EC%9D%BC%EC%B0%A8-1119</link>
            <guid>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-11%EC%9D%BC%EC%B0%A8-1119</guid>
            <pubDate>Thu, 20 Nov 2025 00:33:57 GMT</pubDate>
            <description><![CDATA[<h2 id="1--백준-11650-좌표-정렬하기">1.  <a href="https://www.acmicpc.net/problem/11650">백준 11650 좌표 정렬하기</a></h2>
<blockquote>
<p><strong>아이디어</strong> </p>
</blockquote>
<ul>
<li>정렬 -&gt; Comparator를 람다식으로 표현하기 -&gt; ```Arrays.sort(xy, (a, b) -&gt; {
  if (a[0] != b[0]) {<pre><code>  return a[0] - b[0];</code></pre>  } else {<pre><code>  return a[1] - b[1];</code></pre>  }
});```</li>
<li>추가적 방법 
(삼항 연산자) 
<code>Arrays.sort(xy, (a,b)-&gt; a[0] !=b[0] ? a[0]- b[0] : a[1]-b[1]</code>
(Compator 메서드 체이닝)
<code>Arrays.sort(xy, Comparator.comparingInt(int[] a) -&gt; a[0]).thenComparingInt(a-&gt; a[1]));</code></li>
</ul>
<pre><code class="language-java">package boj_silver.p11650_좌표정렬;
import java.io.*;
import java.util.*;

//좌표정렬: x-&gt; y
public class Review2 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;

        int n = Integer.parseInt(br.readLine());
        int[][] xy = new int[n][2];

        for (int i = 0; i&lt;n; i++){
            st = new StringTokenizer(br.readLine());
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());
            xy[i][0] = a;
            xy[i][1] = b;
        }
        Arrays.sort(xy, (a,b) -&gt; {
            if (a[0] !=b[0]) {
                return a[0] - b[0];
            }else{
                return a[1] - b[1];
            }
        });
        for (int[] num: xy){
            int a = num[0];
            int b = num[1];
            System.out.println(a + &quot; &quot; + b);
        }
        br.close();
        //정렬

    }

}</code></pre>
<h2 id="2-프로그래머스-lv1-k번째-수">2. <a href="https://school.programmers.co.kr/learn/courses/30/lessons/42748">프로그래머스 lv1. k번째 수</a></h2>
<blockquote>
<p><strong>아이디어</strong> 
문제: array의 i번째~j번째 까지 자르고 정렬하고 k번째 있는 수 구하기 </p>
</blockquote>
<ul>
<li>배열 복사 후 정렬해야함. <code>int[] tmp = Arrays.copyOfRange(array, s-1, e);</code></li>
<li>리스트에 tmp[k-1] 추가한다. </li>
<li>리스트를 Array로 바꿈 <code>list.stream().mapToInt(Integer::intValue).toArray();</code></li>
</ul>
<h3 id="stream-기초-문법-및-예시-코드">Stream() 기초 문법 및 예시 코드</h3>
<p>Stream API는 collection, array등의 데이터를 다루기 위한 함수형 프로그래밍 방식을 제공한다. 기능을 구현하지 않고, 선언형으로 컬랙션 형을 처리할 수 있다. (반복문, 조건문) </p>
<h4 id="문법-구조">문법 구조</h4>
<blockquote>
<p>생성하기 - 가공하기 - 결과 만들기 </p>
</blockquote>
<pre><code class="language-java">List&lt;String&gt; fruits = Arrays.asList(&quot;apple&quot;, &quot;banana&quot;, &quot;apple&quot; &quot;orange&quot;, &quot;kiwi&quot;, &quot;watermelon&quot;); 

//1. filter()로 원하는요소 출력하기 
fruits.stream() //stream 생성 
    .filter(fruit-&gt; fruit.startwiith(&quot;a&quot;)) //가공하기 
    .forEach(System.out::println);  //결과 만들기 
    // 출력: apple apple 

// 2. map(): 매핑처리로 리스트 내 모든 값을 키_값 형태로 처리한다. 
fruits.stream()
        .map(fruit -&gt; fruit.toUpperCase())
        .forEach(System.out::println); 
        // 출력: APPLE BANANA APPLE ORANGE KIWI WATERMELON

//3. sorted() 
fruits.stream()
        .sorted()
        .forEach(System.out::println); 
        // 출력: apple apple banana kiwi orange watermelon

//4. reduce()
String result = fruits.stream()
                        .reduce(&quot;&quot;, (s1, s2)-&gt; s1+s2); 
System.out.println(result); 

//5. distinct() 
fruits.stream()
        .distinct()
        .forEach(System.out::println);
        // 출력: apple banana orange kiwi watermelon
//6. limit()
fruits.stream()
        .limit(3) 
        .forEach(System.out::println);
        // 출력: apple banana apple

//7. skip()
fruits.stream()
              .skip(2)
              .forEach(System.out::println);
        // 출력: apple orange kiwi watermelon

//8. count()
long count = fruits.stream()
                    .count(); 
System.out.println(count);  //출력: 6

</code></pre>
<h4 id="stream-중간-연산에서-자주-쓰이는-가공-메서드">Stream 중간 연산에서 자주 쓰이는 가공 메서드</h4>
<ul>
<li>filter() : 특정 조건에 부합하는 stream 전개 </li>
<li>map(): 매핑처리로 리스트내 모든 값을 키/값 형태로 처리한다. </li>
<li>sorted(): 알파벳 순으로 정렬 </li>
<li>reduce(): 모든 과일을 하나의 문자열로 연결한다. </li>
<li>distinct(): 중복된 값을 제거하고 출력 </li>
<li>limit(long maxSize): 처음부터 maxSize개의 값을 출력한다. </li>
<li>skip(long n): 처음 n개의 값을 제외한 나머지값 출력 </li>
</ul>
<h4 id="stream-최종연산에서-자주-쓰이는-메서드">Stream 최종연산에서 자주 쓰이는 메서드</h4>
<ul>
<li>forEach(Consumer<T> action): 각 요소에 대해 주어진 action을 실행한다</li>
<li>count(): 스트림의 요소 수를 반환</li>
<li>collect(Collector&lt;T, A, R&gt; collector): 스트림의 요소를 수집하여 Collection, List, Set, Map 등의 컬렉션에 저장하는 최종 연산</li>
<li>toArray(): 스트림의 요소를 배열로 반환하는 최종 연산</li>
<li>reduce(T identity, BinaryOperator<T> accumulator): 스트림의 요소를 identity로 초기화한 후, accumulator 연산을 반복하여 값을 줄여나가는 최종 연산 예시코드에서는 더하기연산으로 문자열을 이어쓰는 형태로 활용하였다</li>
<li>min(Comparator<T> comparator): 스트림에서 최소값을 반환</li>
<li>max(Comparator<T> comparator): 스트림에서 최대값을 반환</li>
<li>anyMatch(Predicate<T> predicate): 스트림에서 predicate 조건을 만족하는 요소가 하나라도 있는지 확인</li>
<li>allMatch(Predicate<T> predicate): 스트림의 모든 요소가 predicate 조건을 만족하는지 확인</li>
</ul>
<h2 id="3-백준-2750-수-정렬하기">3. <a href="https://www.acmicpc.net/problem/2750">백준 2750 수 정렬하기</a></h2>
<h2 id="4-백준-1181-단어-정렬">4. <a href="https://www.acmicpc.net/problem/1181">백준 1181 단어 정렬</a></h2>
<blockquote>
<p><strong>아이디어</strong></p>
</blockquote>
<ul>
<li>TreeSet으로 중복 제거 + 자동 정렬 =&gt; sb.append()로 출력 </li>
</ul>
<pre><code class="language-java">TreeSet&lt;String&gt; set = new TreeSet&lt;&gt;((a, b) -&gt; {
    if(a.length() != b.length()){
        return a.length() - b.length();
    }
    return a.compareTo(b); 
})

for (String word: set){
    sb.append(word).append(&quot;\n&quot;); 
}</code></pre>
<pre><code class="language-java">package boj_silver.p1181_단어정렬;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;

public class Review2_treeset {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb= new StringBuilder();
        int n = Integer.parseInt(br.readLine());


        //treeset: 중복 제거 + 자동 정렬
        TreeSet&lt;String&gt; set = new TreeSet&lt;&gt;((a,b) -&gt; {
            if(a.length() != b.length()){
                return a.length() - b.length();
            }
            return a.compareTo(b);
        });
//        for (int i = 0; i &lt; strArr.length; i++) {
//            sb.append(strArr[i] + &quot;\n&quot;);
//        }
        for (int i = 0; i&lt;n; i++){
            set.add(br.readLine());
        }
        for (String word: set){
            sb.append(word).append(&quot;\n&quot;);
        }

        System.out.println(sb);
        br.close();
    }
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[정렬 코테 총 정리 ]]></title>
            <link>https://velog.io/@haing3_3/%EC%A0%95%EB%A0%AC-%EC%BD%94%ED%85%8C-%EC%B4%9D-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@haing3_3/%EC%A0%95%EB%A0%AC-%EC%BD%94%ED%85%8C-%EC%B4%9D-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Wed, 19 Nov 2025 02:40:24 GMT</pubDate>
            <description><![CDATA[<p>아래 내용은 코테용  정렬 정리본입니다. </p>
<h1 id="정렬-코테-총-정리">정렬 코테 총 정리</h1>
<h2 id="1-배열-array-정렬">1. 배열 Array 정렬</h2>
<h3 id="1-1-기본-타입-배열-오름차순">1-1 기본 타입 배열 오름차순</h3>
<pre><code class="language-java">int[] arr1 = {5,2,8,1,9}; 
//오름차순 
Arrays.sort(arr1); // 1,2,5,8,9
//범위 지정 정렬 (0~2번 인덱스만 정렬 
Arrays.sort(arr1, 0, 3); // 2,5,8,1,9</code></pre>
<h3 id="1-2-wrapper-클래스-배열-내림차순">1-2 Wrapper 클래스 배열 내림차순</h3>
<pre><code class="language-java">Integer[] arr = {5,2,8,1,9}; 
Arrays.sort(arr, Collections.reverseOrder()); </code></pre>
<h3 id="1-3-string-배열-사전순">1-3 String 배열 (사전순)</h3>
<pre><code class="language-java">String[] strArr = {&quot;banana&quot;, &quot;apple&quot;, &quot;cherry&quot;};
Arrays.sort(strArr); //apple, banana, cherry
</code></pre>
<h3 id="1-4-람다식-정렬">1-4 람다식 정렬</h3>
<pre><code class="language-java">Integer[] arr = {5, 2, 8, 1, 9};
Arrays.sort(arr, (a, b)-&gt; a-b); //오름차순 
Arrays.sort(arr, (a,b)-&gt; b-a); //내림차순 </code></pre>
<h3 id="1-5-복잡한-조건-정렬-홀수-우선-같으면-오름차순">1-5 복잡한 조건 정렬 (홀수 우선, 같으면 오름차순)</h3>
<pre><code class="language-java">Integer[] arr = {5, 2, 8, 1, 9};
Arrays.sort(arr, (o1, o2)-&gt; {
    if(o1 %2 !=0 &amp;&amp; o2%2 ==0) return -1; //o1이 홀수 일때 우선 
    if (o1 % 2 == 0 &amp;&amp; o2 % 2 != 0) return 1; 
    return o1-o2; //오름 차순 
}); </code></pre>
<hr>
<h2 id="2-list-정렬">2. List 정렬</h2>
<h3 id="2-1-collectionssort-사용">2-1 Collections.sort() 사용</h3>
<pre><code class="language-java">List&lt;Integer&gt; list = new ArrayList&lt;&gt;(Arrays.asList(5,2,8,1,9)); 
//오름차순 
Collections.sort(list); 
//내림차순 
Collections.sort(list, Collections.reverseOrder()); </code></pre>
<h3 id="2-2-listsort-사용-java-8">2-2 list.sort() 사용 (java 8+)</h3>
<pre><code class="language-java">list.sort(Comparator.naturalOrder()); 

list.sort(Comparator.reverseOrder()); </code></pre>
<h3 id="2-3-람다식">2-3 람다식</h3>
<pre><code class="language-java">//오름차순 
list.sort((a,b)-&gt; a-b);  </code></pre>
<hr>
<h2 id="3-객체-정렬---comparable-인터페이스">3. 객체 정렬 - Comparable 인터페이스</h2>
<h3 id="person-class에서-compareto-메서드-오버라이드">Person Class에서 compareTo 메서드 오버라이드</h3>
<pre><code class="language-java">Class Person implements Comparable&lt;Person&gt;{
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override 
    public int compareTo(Person other){
        return this.age - other.age; //나이 기준 오름 차순 
    }

    @Override 
    publis String toString(){
        return name + &quot;(&quot; + age + &quot;)&quot;; 
    }

}</code></pre>
<h3 id="main-메서드">main 메서드</h3>
<pre><code class="language-java">List&lt;Person&gt; people = new ArrayList&lt;&gt;(); 
people.add(new Person(&quot;김철수&quot;, 25));
people.add(new Person(&quot;이영희&quot;, 20));
people.add(new Person(&quot;박민수&quot;, 30));

Collections.sort(people); //compareTo()기준 정렬 
//역순 정렬 
Collections.sort(people, Collections.reverseOrder()); 

</code></pre>
<hr>
<h2 id="4-객체-정렬---comparator-인터페이스">4. 객체 정렬 - Comparator 인터페이스</h2>
<h3 id="student-class">Student class</h3>
<pre><code class="language-java">class Student {
    String name;
    int score;
    int age;

    public Student(String name, int score, int age) {
        this.name = name;
        this.score = score;
        this.age = age;
    }

    @Override
    public String toString() {
        return name + &quot;(&quot; + score + &quot;점, &quot; + age + &quot;세)&quot;;
    }
}</code></pre>
<h3 id="main-메서드-1">main 메서드</h3>
<pre><code class="language-java">List&lt;Student&gt; students = new ArrayList&lt;&gt;();
        students.add(new Student(&quot;김철수&quot;, 85, 20));
        students.add(new Student(&quot;이영희&quot;, 90, 22));
        students.add(new Student(&quot;박민수&quot;, 85, 21));
//1. 점수 기준 내림차순
students.sort((s1, s2)-&gt; s2.score - s1.score); 

//2. 점수가 같으면 나이 오름차순    
students.sort((s1,s2) -&gt; {
    if(s1.score!=s2.score){
        return s2.score- s1.score; //점수 내림차순
    }
    return s1.age - s2.age; //나이 오름차순 
} 

//3. Comparator 메서드 체이닝 !! 
students.sort(Comparator.comparingInt((Student s) -&gt; s.score).reversed()
                                                    .thenComparingInt(s-&gt; s.age); 

// 4. 이름 기준 사전 순 
students.sort(Comparator.comparing(s-&gt; s.name)); 
</code></pre>
<hr>
<h2 id="5-2차원-배열-정렬">5. 2차원 배열 정렬</h2>
<pre><code class="language-java">int[][] arr = {{3, 5}, {1, 2}, {5, 3}, {1, 7}};

//1. 첫번째 원소 기준 오름차순 
Arrays.sort(arr, (a, b)-&gt; a[0]- b[0]); 

//2. 첫번째 같으면 두번째 기준 
Arrays.sort(arr, (a, b)-&gt; {
    if(a[0] !=b[0]) return a[0] - b[0]; //첫번째 오름차순 
    return a[1]- b[1]; //두번째 오름차순 
}); 

//3. 두번째 원소 기준 내림차순 
Arrays.sort(arr, (a, b)-&gt; b[1]- a[1]); </code></pre>
<hr>
<h2 id="6-특수-자료-구조-정렬">6. 특수 자료 구조 정렬</h2>
<h3 id="priority-queue-정렬">Priority Queue 정렬</h3>
<pre><code class="language-java">// 1. 최소 힙
PrioriyQueue&lt;Integer&gt; minHeap = new PrioriyQueue&lt;&gt;(); 
minHeap.addAll(Arrays.asList(5,2,8,1,9)); 
//출력- 최소 힙 
while(!minHeap.isEmpty()){
    System.out.print(minHeap.poll() + &quot; &quot; ); 
}

// 2. 최대힙 
PrioriyQueue&lt;Integer&gt; maxHeap = new PrioriyQueue&lt;&gt;(Collections.reverseOrder()); 
maxHeap.addAll(Arrays.asList(5,2,8,1,9)); 
while(!minHeap.isEmpty()){
    System.out.print(minHeap.poll() + &quot; &quot; ); 
}</code></pre>
<h3 id="treeset--자동-정렬--중복-제거">TreeSet- 자동 정렬 + 중복 제거</h3>
<pre><code class="language-java">TreeSet&lt;Integer&gt; treeSet = new TreeSet&lt;&gt;(Arrays.asList(5, 2, 8, 1, 9, 2));
System.out.println(&quot;TreeSet (중복 제거): &quot; + treeSet);</code></pre>
<h3 id="treemap--key자동-정렬">TreeMap- key자동 정렬</h3>
<pre><code class="language-java">TreeMap&lt;String, Integer&gt; treeMap = new TreeMap&lt;&gt;(); 
treeMap.put(&quot;banana&quot;, 3);
treeMap.put(&quot;apple&quot;, 1);
treeMap.put(&quot;cherry&quot;, 2);
System.out.println(&quot;TreeMap: &quot; + treeMap);</code></pre>
<hr>
<h2 id="7-문자열-정렬-특수-케이스">7. 문자열 정렬 특수 케이스</h2>
<pre><code class="language-java">String[] words = {&quot;apple&quot;, &quot;pie&quot;, &quot;banana&quot;, &quot;cat&quot;};

//1. 길이 기준 정렬 
Arrays.sort(words, (a,b) -&gt; a.length() - b.length()); 

//2. 길이 같으면 사전순 
Arrays.sort(words, (a, b)-&gt; {
    if(a.length() != b.length()) return a.length()- b.length(); 
    return a.compareTo(b); 
}); 

//3. 대소문자 구분 없이 정렬 
String[] words3 = {&quot;Apple&quot;, &quot;banana&quot;, &quot;Cherry&quot;};
Arrays.sort(words3, String.CASE_INSENSITIVE_ORDER); 
</code></pre>
<hr>
<h2 id="8-코테용-자주-쓰는-정렬-패턴">8. 코테용 자주 쓰는 정렬 패턴</h2>
<p><code>Integer[] arr1 = {-5, 2, -8, 1, 9};</code></p>
<h3 id="절댓값-기준-정렬">절댓값 기준 정렬</h3>
<p><code>Arrays.sort(arr1, (a,b)-&gt; Math.abs(a)- Math.abs(b));</code>  </p>
<h3 id="특정-값과의-거리-기준-정렬">특정 값과의 거리 기준 정렬</h3>
<pre><code class="language-java">int target = 5; 
Integer[] arr2 = {1, 3, 7, 9, 2};
Arrays.sort(arr2, (a, b)-&gt; Math.abs(a-target)- Math.abs(b-target)); </code></pre>
<h3 id="빈도수-기준-정렬">빈도수 기준 정렬</h3>
<pre><code class="language-java">Integer[] arr3 = {1, 1, 2, 2, 2, 3};
Map&lt;Integer, Integer&gt; freqMap =  new HashMap&lt;&gt;(); 
for (int num: arr3){
    freqMap.put(num, freqMap.getOrDefault(num, 0) +1); 
}
//빈도수 내림차순 
Arrays.sort(arr3, (a,b)-&gt; freqMap.get(b) - freqMap.get(a)); 
</code></pre>
<hr>
<h2 id="9-정렬-주의사항-및-시간-복잡도">9. 정렬 주의사항 및 시간 복잡도</h2>
<h3 id="시간-복잡도">시간 복잡도</h3>
<ul>
<li><strong>Arrays.sort()</strong></li>
</ul>
<p><code>- 기본 타입(int[]): O(n log n) - Dual-Pivot Quicksort”</code></p>
<p><code>- 객체 타입(Integer[]): O(n log n) - TimSort”</code></p>
<h3 id="주의사항">주의사항</h3>
<ul>
<li>int[] 배열은 Comparator 사용 불가 → Integer[] 사용</li>
<li>람다식 (a, b)→ a-b 오버플로우 주의<ul>
<li>안전한것은 Integer.compare(a,b)</li>
</ul>
</li>
<li>내림차순 Collections.reverseOrder()또는 (a,b)→ b-a</li>
</ul>
<h3 id="comparable-vs-comparator">Comparable vs Comparator</h3>
<ul>
<li>Comparable: 클래스 내부에  compareTo() 구현 (기본 정렬)</li>
<li>Comparator: 외부에서 compare() 구현 (사용자 정의 정렬)</li>
</ul>
<h3 id="stable-sort">stable sort</h3>
<ul>
<li>Arrays.sort(객체 배열), Collections.sort() : 안정 정렬 o</li>
<li>Arrays.sort(기본 타입) : 안정 정렬 x</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring MVC 1편] Sec2.웹 애플리케이션의 이해 ]]></title>
            <link>https://velog.io/@haing3_3/Spring-MVC-1%ED%8E%B8-Sec2.%EC%9B%B9-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98%EC%9D%98-%EC%9D%B4%ED%95%B4</link>
            <guid>https://velog.io/@haing3_3/Spring-MVC-1%ED%8E%B8-Sec2.%EC%9B%B9-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98%EC%9D%98-%EC%9D%B4%ED%95%B4</guid>
            <pubDate>Tue, 18 Nov 2025 09:53:16 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h1 id="웹서버--was-서블릿-멀티-쓰레드-csrssr-자바-벡엔드-역사-정리">웹서버 &amp; WAS, 서블릿, 멀티 쓰레드, CSR/SSR, 자바 벡엔드 역사 정리</h1>
</blockquote>
<h1 id="1-웹-서버web-server와-웹-애플리케이션-서버was">1. 웹 서버(Web Server)와 웹 애플리케이션 서버(WAS)</h1>
<h2 id="1-1-모든-것이-http-기반">1-1. 모든 것이 HTTP 기반</h2>
<p>브라우저 ↔ 서버 간의 모든 통신은 <strong>HTTP 프로토콜</strong>을 기반으로 한다.
정적/동적 리소스 제공 방식은 서버 종류에 따라 다르다.</p>
<hr>
<h2 id="1-2-웹-서버web-server">1-2. 웹 서버(Web Server)</h2>
<p>정적 리소스를 제공하는 서버.
(HTML, CSS, JS, 이미지, 영상 파일 등)</p>
<ul>
<li>요청이 오면 파일 그대로 전달</li>
<li>실행 로직 없음 → 가볍고 빠르고 잘 안 죽음</li>
<li>예: <strong>NGINX</strong>, <strong>Apache</strong></li>
</ul>
<hr>
<h2 id="1-3-웹-애플리케이션-서버was">1-3. 웹 애플리케이션 서버(WAS)</h2>
<p>정적 리소스 제공 + <strong>애플리케이션 로직 실행</strong>이 가능한 서버.</p>
<ul>
<li>동적으로 HTML 생성 (JSP, Thymeleaf)</li>
<li>REST API(JSON) 응답</li>
<li>서블릿, JSP, 스프링 MVC 처리</li>
<li>예: <strong>Tomcat</strong></li>
</ul>
<hr>
<h2 id="1-4-웹-서버-vs-was-핵심-정리">1-4. 웹 서버 vs WAS (핵심 정리)</h2>
<table>
<thead>
<tr>
<th>구분</th>
<th>Web Server</th>
<th>WAS</th>
</tr>
</thead>
<tbody><tr>
<td>역할</td>
<td>정적 리소스 제공</td>
<td>애플리케이션 로직 실행</td>
</tr>
<tr>
<td>부하</td>
<td>가벼움</td>
<td>상대적으로 무거움</td>
</tr>
<tr>
<td>예시</td>
<td>NGINX, Apache</td>
<td>Tomcat</td>
</tr>
</tbody></table>
<p><strong>자바 기반에서 서블릿 컨테이너 기능을 제공하면 WAS로 분류됨.</strong></p>
<hr>
<h2 id="1-5-웹-시스템-구성-방식">1-5. 웹 시스템 구성 방식</h2>
<h3 id="✔-was--db">✔ WAS + DB</h3>
<ul>
<li>단독 구성 가능</li>
<li>하지만 <strong>정적 리소스까지 WAS가 떠맡으면 과부하 발생</strong></li>
<li>WAS 장애 시 에러 페이지도 제공할 수 없음</li>
</ul>
<h3 id="✔-web-server--was--db-권장">✔ Web Server + WAS + DB (권장)</h3>
<ul>
<li><p>정적 리소스: Web Server</p>
</li>
<li><p>동적 로직: WAS</p>
</li>
<li><p>장점</p>
<ul>
<li>효율적인 리소스 분리</li>
<li>Web Server는 안정성이 높음</li>
<li>장애 시 Web Server가 에러 페이지 응답 가능</li>
</ul>
</li>
<li><p>REST API만 사용하는 시스템은 Web Server 생략해도 됨</p>
</li>
</ul>
<hr>
<h1 id="2-서블릿servlet">2. 서블릿(Servlet)</h1>
<h2 id="2-1-html-form-데이터-전송">2-1. HTML Form 데이터 전송</h2>
<ul>
<li>브라우저 → 서버로 데이터 전달 시 <strong>POST 요청</strong> 사용</li>
<li>이를 처리하는 것이 서블릿</li>
</ul>
<p>(예: <code>/hello</code> 주소 호출 → HelloServlet 실행)</p>
<hr>
<h2 id="2-2-서블릿의-역할">2-2. 서블릿의 역할</h2>
<ul>
<li><p><strong>HttpServletRequest</strong>
→ 요청 데이터 조회 (<code>request.getParameter()</code> 등)</p>
</li>
<li><p><strong>HttpServletResponse</strong>
→ 응답 메시지 생성 (HTML, JSON 등)</p>
</li>
</ul>
<p>HTTP 스펙을 개발자가 직접 다룰 수 있게 설계된 API라고 보면 됨.</p>
<hr>
<h2 id="2-3-서블릿-요청응답-흐름">2-3. 서블릿 요청/응답 흐름</h2>
<ol>
<li>클라이언트가 HTTP 요청</li>
<li>WAS가 Request/Response 객체 생성</li>
<li>해당 URL 매핑된 서블릿 호출</li>
<li>개발자가 request/response에 데이터를 읽고 쓰기</li>
<li>WAS가 Response 내용을 기반으로 <strong>최종 HTTP 응답 생성</strong></li>
</ol>
<p>→ 개발자는 HTTP 처리 복잡성을 크게 줄일 수 있음.</p>
<hr>
<h2 id="2-4-서블릿-컨테이너was의-핵심-기능">2-4. 서블릿 컨테이너(=WAS의 핵심 기능)</h2>
<p>WAS 내부에서 서블릿을 관리하는 기능을 말함.</p>
<ul>
<li>서블릿 객체 <strong>생성·초기화·종료</strong> 관리</li>
<li><strong>싱글톤</strong>으로 관리 (한 번만 만들고 재사용)</li>
<li>멀티쓰레드 환경 제공 → 동시 요청 처리</li>
<li>JSP는 서블릿으로 변환되어 실행됨</li>
</ul>
<p><strong>주의:</strong>
싱글톤 객체이므로, 공유 변수 사용 시 동시성 문제에 유의해야 한다.</p>
<hr>
<h1 id="3-멀티쓰레드--쓰레드-풀thread-pool">3. 멀티쓰레드 &amp; 쓰레드 풀(Thread Pool)</h1>
<h2 id="3-1-쓰레드thread">3-1. 쓰레드(Thread)</h2>
<ul>
<li>코드 흐름을 수행하는 실행 단위</li>
<li>동시 처리가 필요하면 여러 쓰레드가 사용됨</li>
</ul>
<hr>
<h2 id="3-2-요청마다-쓰레드-생성-방식의-문제">3-2. 요청마다 쓰레드 생성 방식의 문제</h2>
<ul>
<li>쓰레드 생성 비용이 매우 크다</li>
<li>동시 요청 폭주 → 쓰레드 무제한 생성 → CPU/메모리 초과 → 서버 다운</li>
</ul>
<hr>
<h2 id="3-3-was의-해결책-쓰레드-풀thread-pool">3-3. WAS의 해결책: 쓰레드 풀(Thread Pool)</h2>
<p>WAS는 내부적으로 <strong>쓰레드 풀</strong>을 운영한다.</p>
<h3 id="특징">특징</h3>
<ul>
<li><p>미리 쓰레드를 만들어 두고 재사용</p>
</li>
<li><p>요청 → 쓰레드 대여</p>
</li>
<li><p>처리 완료 → 쓰레드 반납</p>
</li>
<li><p>최대 쓰레드 개수 존재</p>
<ul>
<li>Tomcat 기본 200개</li>
</ul>
</li>
</ul>
<h3 id="장점">장점</h3>
<ul>
<li>많은 요청도 안정적으로 처리 가능</li>
<li>개발자는 멀티쓰레드 코드를 직접 구현할 필요가 없음
→ 싱글 쓰레드 코딩하듯 개발해도 됨</li>
</ul>
<hr>
<h2 id="3-4-실무-팁">3-4. 실무 팁</h2>
<ul>
<li>쓰레드 수가 너무 적으면 → CPU는 남는데 처리량 부족</li>
<li>너무 많으면 → 서버가 오히려 장애</li>
<li>적정 숫자는 서비스마다 다르므로 <strong>성능 테스트 필수</strong></li>
</ul>
<h3 id="테스트-도구">테스트 도구</h3>
<ul>
<li>Apache ab</li>
<li>JMeter</li>
<li>nGrinder</li>
</ul>
<hr>
<h1 id="4-html-http-api-csr-ssr-정리">4. HTML, HTTP API, CSR, SSR 정리</h1>
<h2 id="4-1-정적-리소스">4-1. 정적 리소스</h2>
<ul>
<li>변경되지 않는 HTML, CSS, JS 파일</li>
</ul>
<hr>
<h2 id="4-2-html-페이지">4-2. HTML 페이지</h2>
<ul>
<li>JSP/Thymeleaf처럼 <strong>서버가 HTML을 만들어 전달</strong>하는 방식</li>
</ul>
<hr>
<h2 id="4-3-http-api">4-3. HTTP API</h2>
<ul>
<li>HTML이 아닌 <strong>데이터(JSON)</strong> 전달</li>
<li>앱, 웹, 서버 간 통신에 널리 사용</li>
</ul>
<hr>
<h2 id="4-4-ssr-server-side-rendering">4-4. SSR (Server-Side Rendering)</h2>
<p><strong>서버가 HTML 완성본을 만들어 클라이언트에 전송</strong></p>
<ul>
<li>정적인 화면에 적합</li>
<li>JSP, 타임리프</li>
<li>백엔드 중심 구조</li>
</ul>
<hr>
<h2 id="4-5-csr-client-side-rendering">4-5. CSR (Client-Side Rendering)</h2>
<p><strong>HTML을 클라이언트(브라우저)에서 JS로 동적으로 생성</strong></p>
<ul>
<li>React, Vue.js</li>
<li>Gmail, Google Maps처럼 인터랙션이 많은 UI에 적합</li>
</ul>
<p>SSR + CSR 혼합 방식도 가능 (Next.js 등)</p>
<hr>
<h1 id="5-자바-백엔드-기술-역사">5. 자바 백엔드 기술 역사</h1>
<h2 id="5-1-과거">5-1. 과거</h2>
<h3 id="servlet">Servlet</h3>
<ul>
<li>동적 화면 생성 어려움 (HTML 출력 코드를 직접 작성해야 함)</li>
</ul>
<h3 id="jsp">JSP</h3>
<ul>
<li>HTML 렌더링은 편하지만</li>
<li>로직 + 렌더링이 뒤섞여 유지보수 어려움</li>
</ul>
<p>→ MVC 패턴 도입
→ 화면과 비즈니스 로직 분리</p>
<hr>
<h2 id="5-2-현재-spring-mvc--spring-boot">5-2. 현재: Spring MVC &amp; Spring Boot</h2>
<h3 id="spring-mvc">Spring MVC</h3>
<ul>
<li>애노테이션 기반 (<code>@Controller</code>, <code>@RequestMapping</code>)</li>
<li>MVC 아키텍처를 표준으로 자리 잡음</li>
</ul>
<h3 id="spring-boot">Spring Boot</h3>
<ul>
<li>내장 WAS 제공 → Jar 파일만으로 실행 가능</li>
<li>복잡한 설정 자동화</li>
<li>배포 간소화</li>
</ul>
<hr>
<h2 id="5-3-최신-기술-spring-webflux">5-3. 최신 기술: Spring WebFlux</h2>
<h3 id="webflux-reactive">WebFlux (Reactive)</h3>
<ul>
<li>비동기 논블로킹 처리</li>
<li>적은 쓰레드로 높은 성능</li>
<li>함수형 프로그래밍 스타일</li>
</ul>
<p>→ 고성능 &amp; 실시간 스트리밍 시스템에서 유용
→ 하지만 <strong>실무 채택률은 아직 낮음</strong></p>
<hr>
<h2 id="5-4-뷰-템플릿의-역사">5-4. 뷰 템플릿의 역사</h2>
<table>
<thead>
<tr>
<th>기술</th>
<th>특징</th>
</tr>
</thead>
<tbody><tr>
<td>JSP</td>
<td>느리고 기능 제한</td>
</tr>
<tr>
<td>Freemarker / Velocity</td>
<td>빠르고 유연</td>
</tr>
<tr>
<td>Thymeleaf</td>
<td>HTML 구조 그대로 유지(내추럴 템플릿) + 스프링 통합</td>
</tr>
</tbody></table>
<hr>
<h1 id="🔎-전체-흐름-요약">🔎 전체 흐름 요약</h1>
<ul>
<li>Web Server는 정적 파일 제공, WAS는 로직 처리</li>
<li>서블릿은 HTTP 요청을 처리하는 핵심 기반 기술</li>
<li>WAS는 멀티쓰레드 + 쓰레드풀로 동시 요청 처리</li>
<li>Rendering 방식은 SSR, CSR로 나뉨</li>
<li>자바 백엔드는 Servlet → JSP → MVC → Spring MVC → Spring Boot → WebFlux로 발전 중</li>
</ul>
<hr>
<blockquote>
<h2 id="출처">출처</h2>
<p><a href="https://www.inflearn.com/courses/lecture?courseId=326674&amp;type=LECTURE&amp;unitId=71164&amp;tab=curriculum&amp;subtitleLanguage=ko">김영한의 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 매일 풀기 10일차] 1118]]></title>
            <link>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-10%EC%9D%BC%EC%B0%A8-1118</link>
            <guid>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-10%EC%9D%BC%EC%B0%A8-1118</guid>
            <pubDate>Tue, 18 Nov 2025 09:30:42 GMT</pubDate>
            <description><![CDATA[<h2 id="1-백준-9012-괄호">1. <a href="https://www.acmicpc.net/problem/9012">백준 9012 괄호</a></h2>
<blockquote>
<p><strong>아이디어</strong> </p>
</blockquote>
<ul>
<li>입력받는문제: scan.next()로 String 한줄을 입력받고, 문자열 길이만큼 순회하면서 char ch = str.charAt(j)를 입력받는다. </li>
<li>flage로 한번만 출력되게 한다.( &#39;)&#39;가 들어왔는데 비어있으면, no표시만 flag = false로 하고, 마지막 출력때 flag &amp;&amp; stack.isEmpty()조건으로 &quot;YES&quot;를 출력하도록 한다. </li>
</ul>
<pre><code class="language-java">package boj_silver.p9012_괄호;
import java.util.*;

public class Review1 {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int T = scan.nextInt();


        for (int i = 0; i &lt; T; i++) {
            Stack&lt;Character&gt; stack = new Stack&lt;&gt;();
            //Character ch = scan.next().charAt(0);

            //입력 처리
            String str = scan.next(); //문자열 전체를 받음
            boolean isValid = true;

            //문자 하나씩 순회하기 !!
            for (int j = 0; j&lt;str.length(); j++){
                char ch = str.charAt(j);  //하나씩 입력받기
                if (ch ==&#39;(&#39;){
                    stack.push(ch);
                }else if(ch ==&#39;)&#39;){
                    if(stack.isEmpty()){
//                        System.out.println(&quot;NO&quot;);
                        //no표시만
                        isValid = false;

//                        return; //main 종료 -&gt; 전체 종료
                        break; //for문 탈출
                        //continue는 다음 반복으로 건너뛰기
                    }else{
                        stack.pop();
                    }
                }
            }

            //stack에 남아있다면
            if (isValid &amp;&amp; stack.isEmpty()) {
                System.out.println(&quot;YES&quot;);
            } else {
                System.out.println(&quot;NO&quot;); //또 출력되는 문제가 있네-&gt; flag 사용
            }

        }//for
    }//main

}//class</code></pre>
<h2 id="2-백준-21736-헌내기는-친구가-필요해">2. <a href="https://www.acmicpc.net/problem/21736">백준 21736 헌내기는 친구가 필요해 </a></h2>
<blockquote>
<p><strong>아이디어</strong> </p>
</blockquote>
<ul>
<li>I를 만나는 좌표를 저장함 ! -&gt; bfs를 I부터 시작함 </li>
<li>범위 조건&amp; 탐색 조건을 map[nx][ny] !=&#39;X&#39;로 하고, &#39;P&#39;라면 cnt++하는 방식으로 cnt를 셈. </li>
</ul>
<pre><code class="language-java">package boj_silver.p21736_헌내기는친구가;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Queue;
import java.util.StringTokenizer;

//미로 탐색이다.
//nxm의 크기으 ㅣ캠퍼스가 있고,
// O : 빈공간 / X: 벽 / I: 도연이 / P: 사람
//범위 조건에 O, X를 쓰고, P를 만날때 ++ 해서 출력

//도연이가 만날수 있는 사람의 수를 출력 -&gt; 아무도 못만난 경우 TT 출력
public class Main {
    static int n,m, cnt ;
    static int[] dx = {-1,1,0,0};
    static int[] dy = {0,0,-1,1};
    static char[][] map;
    static boolean[][] visited;


    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());
        map = new char[n][m];
        visited= new boolean[n][m];

        int sx =0, sy = 0;
        //map 입력 받기
        for (int i = 0; i &lt; n; i++) {
            String line = br.readLine();
            for (int j = 0; j &lt; m; j++) {
                map[i][j] = line.charAt(j);

                //I를 만나면 bfs 시작
                if (map[i][j] == &#39;I&#39;){
                    sx = i;
                    sy = j;
//                    bfs(i, j);//바로 시작하면 전부다 입력이 안됨,.
                }
            }
        }
        bfs(sx, sy);

        //System.out.println(Arrays.deepToString(map));
        if(cnt&gt;=1){
            System.out.println(cnt);
        }else{
            System.out.println(&quot;TT&quot;);
        }
    }
    static void bfs(int x, int y){
        Queue&lt;int[]&gt; q = new ArrayDeque&lt;&gt;();
        q.offer(new int[]{x,y});
        visited[x][y] = true;
        while(!q.isEmpty()){
            int[] cur = q.poll();
            int cx = cur[0];
            int cy = cur[1];
            for (int i = 0; i&lt;4; i++){
                int nx = cx+dx[i];
                int ny = cy+dy[i];

                if(nx&gt;=0 &amp;&amp; ny&gt;=0 &amp;&amp; nx&lt;n &amp;&amp; ny&lt;m){//가장자리 범위
                    if(!visited[nx][ny] &amp;&amp; map[nx][ny]!=&#39;X&#39;){
                        visited[nx][ny] = true;
                        q.offer(new int[]{nx,ny});
                        if (map[nx][ny] == &#39;P&#39;){
                            cnt++;
                        }
                    }
//                    if(!visited[nx][ny] &amp;&amp; map[nx][ny] == &#39;P&#39;){
//                        //P를 만났을때 처리 !!!! -&gt; 큐에 추가해야함
//                        q.offer(new int[]{nx,ny});
//                        visited[nx][ny] = true;
//                        cnt++;
//                    }
//                    if(!visited[nx][ny] &amp;&amp; map[nx][ny] == &#39;O&#39;){
//                        q.offer(new int[]{nx,ny});
//                        visited[nx][ny] = true;
//
//                    }
                }
            }
        }

    }
}
</code></pre>
<h2 id="3-백준-7576-토마토">3. <a href="https://www.acmicpc.net/problem/7576">백준 7576 토마토</a></h2>
<blockquote>
<p><strong>아이디어</strong> </p>
</blockquote>
<ul>
<li>익은 토마토(1)가 여러개 있을 수 있다 -&gt; list로 좌표 입력 받고 , bfs에 한꺼번에 표시하기 </li>
<li>벽: -1, 안익은 토마토: 0, 익은 토마토: 1 -&gt; visited 배열 필요 없다. </li>
<li>출력은 만약 map에 0이 남아있으면, flag = flase, 아니면, max 변수에, 가장 큰 값을 넣는다. 
!flag이면 -1출력 / max -1 출력 </li>
<li>bfs) queue에 list에 있는 int[] 배열을 동시 추가한다. 
큐가 빌때까지 4방향 탐색을 한다. 범위: 안익은 토마토만 &amp; 벽이 있으면 안됨. <code>map[nx][ny] ==0 &amp;&amp; map[nx][ny]!= -1</code></li>
</ul>
<pre><code class="language-java">package boj_gold.p7576_토마토;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Review1 {
    static int n,m;
    static int[][] map;
//    static boolean [][] visited;
    static int[] dx ={-1,1,0,0};
    static int[] dy ={0,0,-1,1};
    static List&lt;int[]&gt; list;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        m = Integer.parseInt(st.nextToken());
        n = Integer.parseInt(st.nextToken());

        map = new int[n][m];
//        visited = new boolean[n][m];

        //list에 1인 좌표를 큐에 넣기
        list = new ArrayList&lt;&gt;();

        //map 받기
        for (int i = 0; i &lt; n; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j &lt; m; j++) {
                map[i][j] = Integer.parseInt(st.nextToken());
                if(map[i][j] == 1){
                    list.add(new int[]{i,j});
                }
            }
        }
        bfs(list);
//        System.out.println(Arrays.deepToString(map));
        int max= 0;
        boolean flag = true;

        //만약 0이 남아있으면 ?
        for (int i =0; i&lt;n; i++) {
            for (int j = 0; j &lt; m; j++) {
                if (map[i][j] == 0) {
                    flag = false;
                }
                max = Math.max(map[i][j], max);
            }
        }
        if(!flag){
            System.out.println(-1);
        }else{
            System.out.println(max-1);
        }


    }
    static void bfs(List&lt;int[]&gt; list){
        Queue&lt;int[]&gt; q= new ArrayDeque&lt;&gt;();
        //동시 추가
        for (int[] pos: list){
            q.offer(pos);
        }

        while(!q.isEmpty()){
            int[] cur = q.poll();
            int cx = cur[0];
            int cy = cur[1];

            //4방향 탐색
            for(int i =0; i&lt; 4; i++){
                int nx = cx+dx[i];
                int ny = cy+dy[i];
                if (nx &gt;=0 &amp;&amp; ny&gt;=0 &amp;&amp; nx&lt;n &amp;&amp; ny&lt;m){ //범위 체크
                    //안익은 토마토만
                    if(map[nx][ny] ==0 &amp;&amp; map[nx][ny]!= -1){
                        map[nx][ny] = map[cx][cy] + 1;
                        q.offer(new int[]{nx,ny});
                    }

                }
            }

        }
    }
}
</code></pre>
<h2 id="4-백준-1874-스택수열">4. <a href="https://www.acmicpc.net/problem/1874">백준 1874 스택수열</a></h2>
<blockquote>
<p><strong>아이디어</strong> </p>
</blockquote>
<ul>
<li>Stack자료구조 쓰고, flag로 한꺼번에 출력 (StringBuilder) </li>
<li>입력받는 동시에 로직 작성 ! (target은 들어오는 숫자) </li>
<li>cur = 1부터 시작해서, cur&lt;=target까지 push(cur) cur++ </li>
<li>target이 stack.peek()과 같고, stack이 비지 않았다면, pop(); -&gt; else flage = false break; </li>
</ul>
<pre><code class="language-java">package boj_silver.p1847_스택수열;

import java.util.Arrays;
import java.util.Scanner;
import java.util.Stack;

//push 하는 순서는 반드시 오름차순 -&gt;
public class Review1 {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        StringBuilder sb = new StringBuilder();

        //배열 입력받기
//        int[] numbers = new int[n]; // -&gt; 입력받는 동시에 비교하기
//        for (int i = 0; i&lt;n; i++){
//            numbers[i] = scan.nextInt();
//        }

        Stack&lt;Integer&gt; stack = new Stack&lt;&gt;();
        int cur = 1;
        boolean possible = true;
        //while(cur&lt;=target)

        for (int i = 0; i &lt; n; i++) {
            int target= scan.nextInt();
            while(cur&lt;=target){
                stack.push(cur);
                sb.append(&quot;+\n&quot;);
                cur++;
            }
            if(!stack.isEmpty() &amp;&amp; target ==stack.peek()){
                stack.pop();
                sb.append(&quot;-\n&quot;);
            }else{
                possible = false;
                break; //for문 탈출
            }
        }
        if(possible){
            System.out.println(sb);
        }else{
            System.out.println(&quot;NO&quot;);
        }


    }
}
</code></pre>
<h2 id="5-백준-10773-제로">5. <a href="https://www.acmicpc.net/problem/10773">백준 10773 제로</a></h2>
<blockquote>
<p><strong>아이디어</strong> </p>
</blockquote>
<ul>
<li>stack에 있는 것 다 더하기 로직 (while(!stack.isEmpty()){int num = stack.pop(); sum+= num; }</li>
</ul>
<pre><code class="language-java">package boj_silver.p10773_제로;

import java.util.Scanner;
import java.util.Stack;

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        Stack&lt;Integer&gt; stack = new Stack&lt;&gt;();

        for (int i = 0; i &lt; n; i++) {
            int num = scan.nextInt();
            if(num !=0){
                stack.push(num);
            }else if(num ==0){
                stack.pop();
            }
        }
        //stack에 있는 것 다 더하기
        int sum = 0;
        while(!stack.isEmpty()){
            int num = stack.pop();
            sum += num;
        }

        System.out.println(sum);
    }
}

</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 매일 풀기 9일차] 1117]]></title>
            <link>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-9%EC%9D%BC%EC%B0%A8-1117</link>
            <guid>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-9%EC%9D%BC%EC%B0%A8-1117</guid>
            <pubDate>Mon, 17 Nov 2025 05:04:54 GMT</pubDate>
            <description><![CDATA[<p>8일차를 보니 벌써 2주나 쉬었다. 그동안 몸살이나, 스터디 활동이 원활하지 않아, 나태해졌던 것 같다! 
다시 한번 시작하자. </p>
<h2 id="1-백준-2164-카드2">1. <a href="https://www.acmicpc.net/problem/2164">백준 2164 카드2</a></h2>
<blockquote>
<p><strong>아이디어</strong>  </p>
</blockquote>
<ul>
<li>처음에는 Stack으로 구현하였으나, 맨 아래로 넣는 작업에서 FIFO인 Queue로 구현하는것이 맞음. </li>
<li>맨 앞에서 빼기: poll() / 맨 뒤에 추가하기 : offer (), add()</li>
<li>구현 클래스는 LinkedList가 구현한다. </li>
</ul>
<pre><code class="language-java">package boj_silver.p2164_카드2;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        //스택
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        Queue&lt;Integer&gt; q = new LinkedList&lt;&gt;();

        //q에 1부터 ,,N까지 넣기 
        for(int i = 1; i&lt;=n; i++){
            q.offer(i);
        }
        //
        while(true){
            //큐에 있는 개수가 1이 될때 poll하기 -&gt; break 
            if (q.size() ==1){
                int num = q.poll();
                System.out.println(num);
                break;
            }//if

            //맨 첫번째 빼기
            q.poll();
            //맨 위에 있는것 맨 뒤로 보내기
            q.offer(q.poll());
        }
        scan.close();
    }
}
</code></pre>
<h2 id="2-백준-2178-미로탐색">2. <a href="https://www.acmicpc.net/problem/2178">백준 2178 미로탐색</a></h2>
<blockquote>
<p>*<em>아이디어 *</em> </p>
</blockquote>
<ul>
<li>map[n][m] 배열에 거리를 담자! (map[nx][ny] = map[cx][cy] + 1) </li>
<li>주의! 범위 체크! map[nx][ny] ==1 인것만 탐색</li>
</ul>
<h3 id="1-bfs로-풀기">1. bfs로 풀기</h3>
<pre><code class="language-java">package boj_silver.p2178_미로탐색;
import java.util.*;
import java.io.*;

public class Review4 {
    static int n,m;
    static int[][] map;
    static boolean[][] visited;

    static int[] dx ={-1, 1, 0, 0};
    static int[] dy = {0, 0, -1, 1};

    //1,1에서 출발하여, N, M의 위치로 갈때 지나야하는 최소 칸의 개수
    public static void main(String[] args) throws IOException {
        Scanner scan = new Scanner(System.in);


        n = scan.nextInt(); m = scan.nextInt();
        scan.nextLine();
        map= new int[n+1][m+1];
        visited = new boolean[n+1][m+1];

        for (int i= 1; i&lt;=n;i++){
            String line = scan.nextLine();
            for (int j =1; j&lt;=m;j++){
                map[i][j] = line.charAt(j-1)-&#39;0&#39;;
            }
        }//for
//        System.out.println(Arrays.deepToString(map));
        bfs(1,1); 
        System.out.println(map[n][m]);
    }

    static void bfs(int x, int y){

        Queue&lt;int[]&gt; q = new ArrayDeque&lt;&gt;();
        q.offer(new int[]{x,y});
        visited[x][y] = true;

        while (!q.isEmpty()){
            int[] cur = q.poll();
            int cx= cur[0];
            int cy= cur[1];
            //4방향 탐색 
            for (int i = 0; i&lt;4; i++){
                int nx = cx+dx[i];
                int ny = cy+dy[i];
                //범위 조건: 가장 자리 조건 
                if(nx&gt;0 &amp;&amp; ny&gt;0 &amp;&amp; nx&lt;=n &amp;&amp; ny&lt;=m){
                //범위 조건: 탐색하지 않은것, 배열안이 1인것만 탐색 
                    if(!visited[nx][ny] &amp;&amp; map[nx][ny] ==1){
                        visited[nx][ny] = true;
                        q.offer(new int[]{nx,ny});
                        map[nx][ny] = map[cx][cy] +1;
                    }
                }
            }
        }

    }

}
</code></pre>
<h3 id="2-dfs로-풀기">2. dfs로 풀기</h3>
<pre><code class="language-java">
static void main(String[] args){
    visited[1][1]= true; 
    System.out.println(minDistance); 
}//main

static void dfs(int x, int y, int distance){
    //도착 
    if (x==n &amp;&amp; y==m){
        minDistance = Math.min(minDistance, distance); 
        return; 
    }
    //탐색 
    for (int i = 0; i&lt;4; i++){
        int nx = x+dx[i]; 
        int ny = y+ dy[i]; 

        if (nx&gt;0 &amp;&amp; nx&lt;=n &amp;&amp; ny&gt;0 &amp;&amp; ny&lt;=m){
            if (!visited[nx][ny] &amp;&amp; map[nx][ny] ==1){
                visited[nx][ny]= true; 
                dfs(nx, ny, distance+1); 
                visited[nx][ny] = false; //백트래킹 
            }

        }
    }

}
</code></pre>
<h2 id="3-백준-1260-dfs와-bfs">3. <a href="https://www.acmicpc.net/problem/1260">백준 1260 dfs와 bfs</a></h2>
<blockquote>
<p><strong>아이디어</strong></p>
</blockquote>
<ul>
<li><code>LinkedList&lt;Integer&gt;[] list</code> 배열로 받기 </li>
<li>간선 입력 받고, 정렬하기 (Collections.sort(list[i])) </li>
<li>dfs -&gt; bfs로 바꿀때, visited 초기화 </li>
<li>dfs) 현재 정점 방문 처리-&gt; 출력 -&gt; 인접 정점 탐색 (재귀)</li>
<li>bfs) Queue 선언 -&gt; Q offer -&gt; q가 빌때까지 인접 정점 출력</li>
</ul>
<hr>
<pre><code class="language-java">  package boj_silver.p1260_dfs와bfs;

import java.io.*;
import java.util.*;

public class Review1 {
    static int V;
    static boolean[] visited;
    static LinkedList&lt;Integer&gt;[] list;
    //정점 번호가 작은 것 먼저 방문, 더 이상 방문 x-&gt; 종료
    public static void main(String[] args) throws IOException {
        //Linked List&lt;Integer&gt;[] 로 하고, 우선순위 큐
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        V = Integer.parseInt(st.nextToken());

        //n개 생성
        list = new LinkedList[N+1];
        //모든 리스트 초기화
        for (int i = 1; i&lt;=N; i++){
            list[i] = new LinkedList&lt;&gt;();
        }
        //M개 입력 받기
        for (int i = 1; i&lt;= M; i++){
            st = new StringTokenizer(br.readLine());
            //list 초기화 하기
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());
            //양방향 입력-&gt; 정렬하기 작은 것 부터 방문해야한다.
            list[a].add(b);
            list[b].add(a);
        }
        //정렬하기
        for (int i = 1; i&lt;=N; i++){
            Collections.sort(list[i]); //모두 정렬하기
        }
        //첫번째 dfs
        visited = new boolean[N+1];
        dfs(V);
        System.out.println();
        visited = new boolean[N+1];
        bfs(V);
    }
    static void dfs(int v){
        //현재 정점 방문 처리 -&gt; 현재 정점 출력
        visited[v] = true;
        System.out.print(v + &quot; &quot;);

        //인접 정점 탐색 -&gt; 방문 안한 정점 재귀 호출
        // list[v]의 인점 정점 돌면서
        for (int next: list[v]){
            if(!visited[next]){
                dfs(next); // 재귀
            }
        }//
    }

    static void bfs(int v){
        Queue&lt;Integer&gt; q = new ArrayDeque&lt;&gt;();
        q.offer(v);
        visited[v] = true;
        while(!q.isEmpty()){
            int cur = q.poll();
            System.out.print(cur + &quot; &quot;);
            //인접 정점
            for (int next: list[cur]){
                if(!visited[next]){
                    q.offer(next);
                    visited[next] = true;
                }
            }
        }
    }
}
</code></pre>
<h2 id="4-백준-1012-유기농-배추">4. <a href="https://www.acmicpc.net/problem/1012">백준 1012 유기농 배추</a></h2>
<blockquote>
<p><strong>아이디어</strong></p>
</blockquote>
<h3 id="1-배추-있는-좌표-리스트에-yx순으로-저장함">1. 배추 있는 좌표 리스트에 {y,x}순으로 저장함.</h3>
<pre><code class="language-java">package boj_silver.p1012유기농배추;
//몇개의 bfs가 호출되는지 !
import java.io.*;
import java.util.*;

public class Main {
    static boolean[][] visited;
    static int m,n;
    static int[][] map;
    static int[] dx = { 0, 1, 0, -1 };
    static int[] dy = { 1, 0, -1, 0 };

    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st ;

        int T = Integer.parseInt(bf.readLine());
        for (int i = 0; i &lt; T; i++) {
            st = new StringTokenizer(bf.readLine());
            m = Integer.parseInt(st.nextToken());
            n = Integer.parseInt(st.nextToken());
            int k = Integer.parseInt(st.nextToken());//배추의 개수

            ArrayList&lt;int[]&gt; list = new ArrayList&lt;&gt;();
            map = new int[n][m];

            visited = new boolean[n][m]; //초기화
            //k의 줄에 배추의 위치가 저장
            for (int j = 0; j&lt; k; j++){
                st = new StringTokenizer(bf.readLine());
                int x = Integer.parseInt(st.nextToken()); //가로 좌표
                int y = Integer.parseInt(st.nextToken());//세로 좌표
                list.add(new int[]{y,x});
                map[y][x] = 1;
            }// list에 있는 것 돌면서 !

            //boolean[] listVisited = new boolean[list.size()];

            int sum = 0;
            for (int[] cur: list){
                if (!visited[cur[0]][cur[1]]){
                    bfs(cur[0], cur[1]);
                    sum++;
                }

            }
            System.out.println(sum);
        }

        bf.close();
    }//main
    static void bfs(int x, int y){
        Queue&lt;int[]&gt; q = new ArrayDeque&lt;&gt;();
        q.add(new int[]{x,y});
        visited[x][y] = true;
        while(!q.isEmpty()){
            int [] cur = q.poll();
            int cx = cur[0];
            int cy = cur[1];
            for (int i = 0; i &lt; 4; i++) {
                int nx = cx+ dx[i];
                int ny = cy+ dy[i];
                if (nx&gt;=0 &amp;&amp; nx&lt;n &amp;&amp; ny&gt;=0 &amp;&amp; ny&lt;m){
                    if(!visited[nx][ny] &amp;&amp; map[nx][ny]==1 ) {
                        q.offer(new int[]{nx,ny});
                        visited[nx][ny] = true;
                    }

                }

            }//for
        }

    }
}
</code></pre>
<h3 id="2-리스트-없이-2중-for문">2. 리스트 없이 2중 for문</h3>
<blockquote>
<h4 id="-아이디어">** 아이디어**</h4>
<p> ** 1번** 
입력받을때 리스트에 좌표를 저장한다. (가로, 세로)로 주어짐 -&gt; list.add(new int[] {y,x}) 로 저장 
map[y][x] = 1; 
-&gt; 리스트에 있는 배추만 확인 
<strong>2번: 2중 for문</strong> 
입력받을때 map에만 저장한다. map[y][x] = 1; 
전체 map을 순회하면서 배추를 찾는다. 
==&gt; 둘다 괜찮으나, 리스트를 사용하는 경우는, K가 훨씬 작을때 사용하고, 2중 for문은 코드 간결성과 K가 nxm에 가까울때 </p>
</blockquote>
<pre><code class="language-java">//map 전체를 돌면서, 
package boj_silver.p1012유기농배추;
//몇개의 bfs가 호출되는지 !

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main_effi {
    static boolean[][] visited;
    static int m,n;
    static int[][] map;
    static int[] dx = { 0, 1, 0, -1 };
    static int[] dy = { 1, 0, -1, 0 };

    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st ;

        int T = Integer.parseInt(bf.readLine());
        for (int i = 0; i &lt; T; i++) {
            st = new StringTokenizer(bf.readLine());
            m = Integer.parseInt(st.nextToken());
            n = Integer.parseInt(st.nextToken());
            int k = Integer.parseInt(st.nextToken());//배추의 개수

            //ArrayList&lt;int[]&gt; list = new ArrayList&lt;&gt;();
            map = new int[n][m];
            visited = new boolean[n][m]; //초기화

            //k의 줄에 배추의 위치가 저장
            for (int j = 0; j&lt; k; j++){
                st = new StringTokenizer(bf.readLine());
                int x = Integer.parseInt(st.nextToken()); //가로 좌표
                int y = Integer.parseInt(st.nextToken());//세로 좌표
                //list.add(new int[]{y,x});
                map[y][x] = 1;
            }// list에 있는 것 돌면서 !

            //boolean[] listVisited = new boolean[list.size()];
            //전체 맵 탐색
            int cnt =0;
            for (int x =0; x&lt;n;x++){
                for (int y =0; y&lt;m;y++){
                    if(map[x][y] ==1 &amp;&amp; !visited[x][y]){
                        bfs(x,y);
                        cnt++;
                    }
                }
            }
            System.out.println(cnt);


//            int sum = 0;
//            for (int[] cur: list){
//                if (!visited[cur[0]][cur[1]]){
//                    bfs(cur[0], cur[1]);
//                    sum++;
//                }
//
//            }
//            System.out.println(sum);
        }

        bf.close();
    }//main
    static void bfs(int x, int y){
        Queue&lt;int[]&gt; q = new ArrayDeque&lt;&gt;();
        q.add(new int[]{x,y});
        visited[x][y] = true;
        while(!q.isEmpty()){
            int [] cur = q.poll();
            int cx = cur[0];
            int cy = cur[1];
            for (int i = 0; i &lt; 4; i++) {
                int nx = cx+ dx[i];
                int ny = cy+ dy[i];
                if (nx&gt;=0 &amp;&amp; nx&lt;n &amp;&amp; ny&gt;=0 &amp;&amp; ny&lt;m){
                    if(!visited[nx][ny] &amp;&amp; map[nx][ny]==1 ) {
                        q.offer(new int[]{nx,ny});
                        visited[nx][ny] = true;
                    }

                }

            }//for
        }

    }
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 매일 풀기 8일차] 1103]]></title>
            <link>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-8%EC%9D%BC%EC%B0%A8-1103</link>
            <guid>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-8%EC%9D%BC%EC%B0%A8-1103</guid>
            <pubDate>Mon, 03 Nov 2025 10:00:02 GMT</pubDate>
            <description><![CDATA[<h2 id="백준-16234-인구-이동"><a href="https://www.acmicpc.net/problem/16234">백준 16234 인구 이동 </a></h2>
<blockquote>
<p>**아이디어 </p>
</blockquote>
<ul>
<li>처음에 bfs로 했을때 안풀림!!! </li>
<li>인구 이동이 발생하는 동안 while문으로 접근해서 이동이 발생하면, day추가하는 방식으로 함. </li>
</ul>
<pre><code class="language-java"> javapackage boj_gold.p16234_인구이동;

import java.io.*;
import java.util.*;

public class Review1 {
    // 전역 변수 선언
    static int[][] map;           // N x N 크기의 땅 (각 칸의 인구수)
    static boolean[][] visited;   // BFS 방문 체크 배열
    static int[] dx = {-1, 1, 0, 0};  // 상하좌우 x
    static int[] dy = {0, 0, -1, 1};  // 상하좌우 y 
    static int N, L, R;           //  입력 받기 
    static boolean isMoved;       // 인구 이동 발생 여부 플래그

    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());
        L = Integer.parseInt(st.nextToken());
        R = Integer.parseInt(st.nextToken());

        // 맵 초기화 및 입력
        map = new int[N][N];
        for (int i = 0; i &lt; N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j &lt; N; j++) {
                map[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        int day = 0;  // 인구 이동이 며칠 동안 발생하는지 카운트

        // 인구 이동이 없을 때까지 반복
        while (true) {
            // 매일 visited 배열 초기화
            visited = new boolean[N][N];
            // 이동 발생 여부 초기화 (false부터 시작)
            isMoved = false;

            // 전체 맵을 순회하면서 연합 찾기
            for (int i = 0; i &lt; N; i++) {
                for (int j = 0; j &lt; N; j++) {
                    // 아직 방문하지 않은 칸이면 BFS로 연합 찾기
                    if (!visited[i][j]) {
                        bfs(i, j);
                    }
                }
            }

            // 인구 이동이 발생했으면 day 증가
            if (isMoved) {
                day++;
            } else {
                // 인구 이동이 발생하지 않았으면 종료
                break;
            }
        }

        // 결과 출력 (인구 이동이 며칠 동안 발생했는지)
        System.out.println(day);
    }

    /**
     * BFS를 이용해 (x, y)에서 시작하는 연합을 찾고 인구 이동 처리
     */
    static void bfs(int x, int y) {
        Queue&lt;int[]&gt; q = new ArrayDeque&lt;&gt;();        // BFS 탐색용 큐
        List&lt;int[]&gt; union = new ArrayList&lt;&gt;();      // 연합에 속한 칸들을 저장

        // 시작 칸을 큐와 연합에 추가
        q.offer(new int[]{x, y});
        union.add(new int[]{x, y});
        visited[x][y] = true;

        int sum = map[x][y];  // 연합의 총 인구수 (시작 칸의 인구수로 초기화)

        // BFS 탐색 시작
        while (!q.isEmpty()) {
            int[] cur = q.poll();
            int cx = cur[0];  // 현재 x 좌표
            int cy = cur[1];  // 현재 y 좌표

            // 상하좌우 4방향 탐색
            for (int i = 0; i &lt; 4; i++) {
                int nx = cx + dx[i];  // 다음 x 좌표
                int ny = cy + dy[i];  // 다음 y 좌표

                // 경계 체크 및 방문 체크
                if (0 &lt;= nx &amp;&amp; nx &lt; N &amp;&amp; 0 &lt;= ny &amp;&amp; ny &lt; N &amp;&amp; !visited[nx][ny]) {
                    // 현재 칸과 다음 칸의 인구 차이 계산
                    int diff = Math.abs(map[cx][cy] - map[nx][ny]);

                    // 인구 차이가 L 이상 R 이하이면 연합 형성 가능
                    if (diff &gt;= L &amp;&amp; diff &lt;= R) {
                        q.offer(new int[]{nx, ny});      // 큐에 추가 (BFS 계속)
                        union.add(new int[]{nx, ny});    // 연합에 추가
                        visited[nx][ny] = true;          // 방문 처리
                        sum += map[nx][ny];              // 연합의 총 인구수에 더하기
                    }
                }
            }
        }

        // 연합이 2개 이상의 칸으로 이루어진 경우에만 인구 이동 발생
        if (union.size() &gt;= 2) {
            // 연합의 평균 인구수 계산
            int avg = sum / union.size();

            // 연합에 속한 모든 칸의 인구수를 평균값으로 업데이트
            for (int[] pos : union) {
                map[pos[0]][pos[1]] = avg;
            }

            // 인구 이동이 발생했음을 표시
            isMoved = true;
        }
    }
}
</code></pre>
<pre><code class="language-java">package boj_gold.p16234_인구이동;
//인구 이동이 얼마나 걸리는지 .
//인구이동이 일어나는 조건: 두 나라의 인구 차이가 L명 R명 이하 -&gt;
//visited[] -&gt; bfs 사용
// 방향 둘러가면서, 차이가 L, R 사이면 -&gt; bfs 호출 -&gt; count + 1
// 인구 이동 안하면 바로 0 출력 -&gt; return
//count 출력

import java.io.*;
import java.util.*;

public class Review1 {
    static int[][] map;
    static boolean[][] visited;
    static int[] dx = {-1, 1, 0,0};
    static int[] dy = {0,0,-1,1};
    static int N, L, R;
    static Queue&lt;int[]&gt; q;
    static boolean isMoved;
    static int sum;


    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());
        L = Integer.parseInt(st.nextToken());
        R = Integer.parseInt(st.nextToken());
        map = new int[N][N];
        //
        for (int i = 0; i&lt; N; i++){
            st = new StringTokenizer(br.readLine());
            for (int j =0; j&lt;N; j++){
                map[i][j] = Integer.parseInt(st.nextToken());
            }
        }
        int day = 0;
        //인구이동이 발생하는 동안
        while(isMoved) {
            //visited 초기화
            visited = new boolean[N][N];
            //이동 발생 여부
            isMoved = false;
            //전체 맵 순회하면서
            for (int i = 0; i &lt; N; i++) {
                for (int j = 0; j &lt; N; j++) {
                    if (!visited[i][j]) {
                        //bfs로 연합 찾기
                        bfs(i, j);

                        isMoved = true;
                    }
                }
            }//for

            //만약 이동이 발생하면
            if(isMoved){
                day++;
            }else break;
        }//while
        System.out.println(day);

//        System.out.println(Arrays.deepToString(map));

        //일단 (0,0부터 시작하기)
        //만약 호출을 안하면 넣어줘야 함...........
//        int count =0;
//        q = new ArrayDeque&lt;&gt;();
//        for(int i = 0; i&lt; N; i++){
//            for (int j = 0; j&lt; N; j++){
//                if(!visited[i][j]){
//                    q.offer(new int[] {i,j});
//                    int sum = bfs(i, j, 0);
//                    count++;
//                }
//            }
//        }
//        System.out.println(count);


    }//main
    static void bfs(int x, int y){
        //돌면서 찾기
        Queue&lt;int[]&gt; q = new ArrayDeque&lt;&gt;();
        //연합에 속한 칸 저장
        List&lt;int[]&gt; union = new ArrayList&lt;&gt;();

        q.offer(new int[]{x,y});
        union.add(new int[]{x,y});
        visited[x][y] = true;
        while(!q.isEmpty()){
            int[] cur = q.poll();
            int cx = cur[0];
            int cy = cur[1];

            for(int i =0; i&lt;4; i++){
                //이동하면서 차이가 L, R사이이면,
                int nx = cx+ dx[i];
                int ny = cy + dy[i];

                if (0&lt;=nx &amp;&amp; nx &lt;N &amp;&amp; 0&lt;=ny &amp;&amp; ny&lt;N &amp;&amp; !visited[nx][ny]){
                    int diff = Math.abs(map[cx][cy] - map[nx][ny]);
                    if (diff&gt;=L &amp;&amp; diff&lt;=R){
                        //이동
                        q.offer(new int[]{nx,ny});
                        union.add(new int[]{nx,ny});
                        visited[nx][ny] = true;
                        sum += map[nx][ny];
                        //bfs(nx, ny, sum+map[cx][cy]);
                    }
                }
            }
        }//while
        //현재
        //union이 2개이상이라면 ?

        if(union.size()&gt;1){
            //평균 계산
            int avg  = sum/union.size();
            for (int[] pos: union){
                map[pos[0]][pos[1]] = avg;//map 업데이트
            }
            isMoved = true;
        }


    }


//    static int bfs(int x, int y, int sum){
//        q.offer(new int[] {x,y});
//        visited[x][y] = true;
//        //현재
//        int[] cur = q.poll();
//        int cx = cur[0];
//        int cy = cur[1];
//
//        cnt =0;
//        for (int i = 0; i&lt; 4; i++){
//            //이동하면서 차이가 L이상 R이하라면, 일단 더함
//            int nx = x+ dx[i];
//            int ny = y+ dy[i];
//            if (0&lt;=nx &amp;&amp; nx &lt;N &amp;&amp; 0&lt;=ny &amp;&amp; ny&lt;N &amp;&amp; !visited[nx][ny]){//경계선
//                int diff = Math.abs(map[cx][cy] - map[nx][ny]);
//                if (diff&gt;=L &amp;&amp; diff&lt;=R){
//                    //이동
//                    bfs(nx, ny, sum + map[cx][cy]);
//                    cnt++;
//                }
//
//            }
//        }//for
//        return sum;
//    }
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 매일 풀기 7일차] 1031]]></title>
            <link>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-7%EC%9D%BC%EC%B0%A8-1031</link>
            <guid>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-7%EC%9D%BC%EC%B0%A8-1031</guid>
            <pubDate>Mon, 03 Nov 2025 00:51:37 GMT</pubDate>
            <description><![CDATA[<h2 id="백준-16234-인구이동"><a href="https://www.acmicpc.net/problem/16234">백준 16234 인구이동</a></h2>
<pre><code class="language-java">package boj_bronze.p3040_백설공주와일곱난쟁이;
import java.util.*;

public class Review1 {
    // 아이디어: 9개의 요소를 다 더한 후 100을 빼면, 제거해야할 2명의 난쟁이가 남는다. 
    static int[] nums; //9개 숫자 넣을 배열 

    public static void main(String[] args) {
        //입력 받기
        Scanner scan = new Scanner(System.in);
        nums = new int[9];

        int sum  =0;
        for (int i = 0; i &lt; 9; i++){
            nums[i] = scan.nextInt();
            sum+= nums[i];
        }
        //100에서 sum을 뺀 값이 난쟁이가 아닌 두 수를 더한 후보이다.
        int target_num = sum - 100;
        int n1  = -1, n2 = -1;
        // 두 숫자 찾기
        //두숫자를 더해 target_num이면 제거를 하는것
        for (int i = 0; i&lt; 9; i++){
            //nums배열에서 두 값을 더해서 target_num인 두 값을 찾기
            for (int j = i+1; j &lt; 9; j++){
                if (nums[i] + nums[j] == target_num){
                    n1 = i;//인덱스 저장
                    n2 = j; //인덱스 저장
                    break;
                }
            }
        }//for
        //출력
        for (int i = 0; i&lt; 9; i++){
            if (i!=n1 &amp;&amp; i !=n2){
                System.out.println(nums[i]);
            }
        }
        scan.close();
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 매일 풀기 6일차] 1030 ]]></title>
            <link>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-6%EC%9D%BC%EC%B0%A8-1030</link>
            <guid>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-6%EC%9D%BC%EC%B0%A8-1030</guid>
            <pubDate>Thu, 30 Oct 2025 09:37:25 GMT</pubDate>
            <description><![CDATA[<h2 id="백준-11720-숫자의-합"><a href="https://www.acmicpc.net/problem/11720">백준 11720 숫자의 합</a></h2>
<blockquote>
<p><strong>아이디어</strong> </p>
</blockquote>
<ul>
<li>입력을 받는게 은근 쉽지 않네 </li>
<li>공백없이 숫자 받기 -&gt; ? </li>
<li>그냥 String으로 받아서 charAt()-&#39;0&#39;으로 받기 </li>
</ul>
<h3 id="나의-문제-풀이-과정">나의 문제 풀이 과정</h3>
<ul>
<li>scanner로 입력을 받을때, scan.nextInt()로 받으면 &#39;\n&#39;의 개행문자가 남아 입력부분이 잘 처리가 안되었음. </li>
<li><blockquote>
<p>scan.nextLine()으로 받기 </p>
</blockquote>
</li>
</ul>
<pre><code class="language-java">public class Review1 {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int N = Integer.parseInt(scan.nextLine());

        //배열 생성
        int[] array = new int[N];

        String line = scan.nextLine();

        //N개만큼 받기
        for (int i = 0; i&lt; N ; i++) {
            array[i] = line.charAt(i) - &#39;0&#39;;
        }

        for (int i = 0; i&lt; N ; i++) {
            System.out.println(array[i]);
        }
    }
}
</code></pre>
<h2 id="코테에서-입력-꿀팁">코테에서 입력 꿀팁</h2>
<h3 id="1-n개의-정수-한줄에">1. N개의 정수 한줄에</h3>
<pre><code class="language-java">//입력: 5 5 4 3 2 1 
int n = scan.nextInt(); 
int[] arr = new int[n]; 
for (int i=0; i&lt;n; i++){
    arr[i] = scan.nextInt(); 
}</code></pre>
<h3 id="2-공백으로-구분된-숫자---bufferedreader--stringtokenizer">2. 공백으로 구분된 숫자 -&gt; BufferedReader + StringTokenizer</h3>
<pre><code class="language-java">//입력: 1 2 3 4 5
String[] input = bf.readLine().split(&quot; &quot;); 
int[] arr = new int[input.length]; 
for (int i = 0; i&lt; input.length; i++){
    arr[i] = Integer.parseInt(input[i]); 

//또는 String Tokenizer
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); 
 StringTokenizer st = new StringTokenizer(bf.readLine()); 
 int N = Integer.parseInt(st.nextToken()); 
}</code></pre>
<h3 id="3-붙어-있는-숫자들">3. 붙어 있는 숫자들</h3>
<pre><code class="language-java">//입력: 12345
String line = bf.readine(); 
int[] arr = new int[line.length()]; 
for (int i = 0; i&lt; line.length(); i++){
    arr[i] = line.charAt(i)- &#39;0&#39;; 
}</code></pre>
<h3 id="4-2차원-배열-받기">4. 2차원 배열 받기</h3>
<pre><code class="language-java">// 입력: 
// 3 4
// 1 2 3 4
// 5 6 7 8
// 9 10 11 12

int n = scan.nextInt(); 
int m - scan.nextInt(); 
int[][] arr = new int[n][m]; 
for (int i = 0; i&lt; n; i++){
    for(int j = 0; j&lt; m; j){
            arr[i][j] = scan.nextInt(); 
    }
}</code></pre>
<h3 id="5-끝까지-읽기-eof까지-읽기">5. 끝까지 읽기 (EOF까지 읽기)</h3>
<pre><code class="language-java">//scanner 
while(scan.hasNext()){
    int n = scan.nextInt(); 
    //처리 
}</code></pre>
<h3 id="6-빠른-출력">6. 빠른 출력</h3>
<pre><code class="language-java">StringBuilder sb = new StringBuilder(); 
for (int i =0; i&lt; n; i++_){
    sb.append(i).append(&quot;\n&quot;); 
}
System.out.print(sb); </code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 매일 풀기 5일차] 1029]]></title>
            <link>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-5%EC%9D%BC%EC%B0%A8-1029</link>
            <guid>https://velog.io/@haing3_3/%EC%BD%94%ED%85%8C-%EB%A7%A4%EC%9D%BC-%ED%92%80%EA%B8%B0-5%EC%9D%BC%EC%B0%A8-1029</guid>
            <pubDate>Wed, 29 Oct 2025 07:25:53 GMT</pubDate>
            <description><![CDATA[<h2 id="백준-11724-연결-요소의-개수"><a href="https://www.acmicpc.net/problem/11724">백준 11724 연결 요소의 개수</a></h2>
<blockquote>
<p><strong>아이디어</strong> </p>
</blockquote>
<ul>
<li>union-find 알고리즘으로 root의 개수를 세자 </li>
</ul>
<pre><code class="language-java">//union -find로 루트 요소 개수 세기
public class Review2 {
    static int[] nodes;
    public static void main(String[] args) {
        //입력 받기
        Scanner scan = new Scanner(System.in);
        int N = scan.nextInt();
        int M = scan.nextInt();
        nodes = new int[N+1];
        for (int i =1; i &lt;=N ; i++){
            nodes[i] = i;
        }//nodes
        for (int i = 0; i &lt; M; i++){
            int a = scan.nextInt();
            int b = scan.nextInt();
            union(a, b); // union 연산
        }

//        //각 노드의 루트를 찾아 고유한 루트 개수 세기 =&gt; 안됨 : 정렬이 안되어 있기 때문에 중복 발생 
//        int cnt = 0;
//        for (int i = 1 ; i &lt;N ; i++){
//            if (nodes[i] == nodes[i+1]){
//                cnt++;
//            }
//        }
        //System.out.println(cnt);

        // 최종 루트 찾는 방법
        Set&lt;Integer&gt; roots = new HashSet&lt;&gt;();
        for (int i = 1; i&lt;=N; i++){
            roots.add(find(i));
        }
        System.out.println(roots.size());
    }

    //a,b 합집합 연산 
    static void union(int a, int b){
        int rootA = find(a); //a의 루트 노드 찾기
        int rootB = find(b); //b의 루트 노드 찾기
        if (rootA == rootB) return; //부모가 같으면 바로 return 
        nodes[rootB] = rootA; // 부모가 다르면, 다른 루트에 할당시킴 (합집합) 
    }
    //부모 찾기 
    static int find(int a){
        if (nodes[a] == a) return a; //자기 자신이 부모이면 자신 return 
        return nodes[a]= find(nodes[a]); //부모를 재귀적으로 찾음 
    }
}



</code></pre>
]]></description>
        </item>
    </channel>
</rss>