<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jh_y.log</title>
        <link>https://velog.io/</link>
        <description>안녕하세요.</description>
        <lastBuildDate>Fri, 18 Apr 2025 16:40:36 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>jh_y.log</title>
            <url>https://velog.velcdn.com/images/jh_y/profile/d313d16d-d0dc-4f83-89d8-e042314f5eb5/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. jh_y.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jh_y" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[리눅스]]></title>
            <link>https://velog.io/@jh_y/%EB%A6%AC%EB%88%85%EC%8A%A4</link>
            <guid>https://velog.io/@jh_y/%EB%A6%AC%EB%88%85%EC%8A%A4</guid>
            <pubDate>Fri, 18 Apr 2025 16:40:36 GMT</pubDate>
            <description><![CDATA[<h4 id="step-1-gcc로-컴파일">Step 1. <code>gcc</code>로 컴파일</h4>
<pre><code class="language-bash">gcc -o app app.c
</code></pre>
<ul>
<li><code>gcc</code> : GNU C 컴파일러</li>
<li><code>o app</code> : 컴파일 결과 파일 이름을 <code>app</code>으로 지정</li>
<li><code>app.c</code> : 소스 파일 이름</li>
</ul>
<h4 id="step-2-컴파일된-실행-파일-실행">Step 2. 컴파일된 실행 파일 실행</h4>
<pre><code class="language-bash">./app
</code></pre>
<h4 id="컴파일된-파일-목록-보기">컴파일된 파일 목록 보기</h4>
<pre><code class="language-bash">ls -l
</code></pre>
<p>컴파일 후 <code>app</code>이라는 실행 파일이 생긴 걸 확인할 수 있어야 합니다.</p>
<p>gcc 컴파일러 코드(여러 파일로 나눠서 작업한 경우)</p>
<pre><code class="language-bash">gcc -c rbtree.c -o rbtree.o</code></pre>
<p>gcc 컴파일러 코드(단일 파일인 경우)</p>
<pre><code class="language-bash">gcc -o app app.c</code></pre>
<h4 id="전체-과정의-흐름-요약">전체 과정의 흐름 요약</h4>
<table>
<thead>
<tr>
<th>단계</th>
<th>명령어</th>
<th>결과</th>
</tr>
</thead>
<tbody><tr>
<td>1단계: 컴파일</td>
<td><code>gcc -c app.c -o app.o</code></td>
<td>목적 파일 <code>app.o</code> 생성</td>
</tr>
<tr>
<td>2단계: 링크</td>
<td><code>gcc app.o -o app</code></td>
<td>실행 파일 <code>app</code> 생성</td>
</tr>
</tbody></table>
<p>make clean
make test
vi
cd
ls</p>
<p>vi ~/.vimrc (초반 세팅 파일)
<img src="https://velog.velcdn.com/images/jh_y/post/4beb8afd-9d84-40c8-a8e2-77e3a44f5599/image.png" alt=""></p>
<p>aws 가상컴퓨터 접속하기.</p>
<p>```bash
% ssh -i 키파일 ubuntu@퍼블릭 주소</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[C언어 역순서 구현(재귀함수)]]></title>
            <link>https://velog.io/@jh_y/C%EC%96%B8%EC%96%B4-%EC%97%AD%EC%88%9C%EC%84%9C-%EA%B5%AC%ED%98%84%EC%9E%AC%EA%B7%80%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@jh_y/C%EC%96%B8%EC%96%B4-%EC%97%AD%EC%88%9C%EC%84%9C-%EA%B5%AC%ED%98%84%EC%9E%AC%EA%B7%80%ED%95%A8%EC%88%98</guid>
            <pubDate>Mon, 14 Apr 2025 13:57:54 GMT</pubDate>
            <description><![CDATA[<blockquote>
</blockquote>
<pre><code class="language-c">void RecursiveReverse(ListNode **ptrHead) //ll.head를 가르키는 이중포인터변수를 받음
{
    /* add your code here */
    if ((*ptrHead)==NULL || (*ptrHead)-&gt;next==NULL) return; //헤드값이 없거나 연결리스트가 값이 없을 때 함수를 종료한다.
    ListNode *first=*ptrHead,*rest=first-&gt;next;//두가지 포인터변수 생성. ll.head값이 저장된 first, head 다음값인 rest.
    RecursiveReverse(&amp;rest); // 재귀함수를 선언한다.위의 함수가 주소를 받는 이중포인터변수라 주소값을 넣음.
    first-&gt;next-&gt;next=first; //밀린 재귀들을 내려받으면서 노드의 순서를 바꿔준다. rest(5)-&gt;next=first(4) ,rest(4)-&gt;next=first(3)
    first-&gt;next=NULL;//first 이후의 노드의 연결을 끊어준다. 5-&gt;4-&gt;NULL 이렇게 만들어짐
    *ptrHead=rest; //rest는 마지막으로 4의 값이 재귀함수위에서 저장되었을때가 마지막이라 값은 5로 고정됨.
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[레지스터]]></title>
            <link>https://velog.io/@jh_y/%EB%A0%88%EC%A7%80%EC%8A%A4%ED%84%B0</link>
            <guid>https://velog.io/@jh_y/%EB%A0%88%EC%A7%80%EC%8A%A4%ED%84%B0</guid>
            <pubDate>Sun, 06 Apr 2025 16:19:59 GMT</pubDate>
            <description><![CDATA[<h3 id="함수-호출-시-사용하는-주요-레지스터들">함수 호출 시 사용하는 주요 레지스터들:</h3>
<table>
<thead>
<tr>
<th>종류</th>
<th>레지스터</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><strong>인자 전달용</strong></td>
<td><code>%rdi</code>, <code>%rsi</code>, <code>%rdx</code>, <code>%rcx</code>, <code>%r8</code>, <code>%r9</code></td>
<td>첫 6개의 인자 전달 (x86-64 System V 기준)</td>
</tr>
<tr>
<td><strong>리턴값</strong></td>
<td><code>%rax</code></td>
<td>함수 결과가 여기에 담김</td>
</tr>
<tr>
<td><strong>스택 포인터</strong></td>
<td><code>%rsp</code></td>
<td>현재 스택의 top을 가리킴</td>
</tr>
<tr>
<td><strong>프레임 포인터</strong></td>
<td><code>%rbp</code></td>
<td>이전 스택 프레임의 기준점</td>
</tr>
<tr>
<td><strong>임시 계산용</strong></td>
<td><code>%rax</code>, <code>%rcx</code>, <code>%rdx</code>, ...</td>
<td>연산 중간 저장에 사용</td>
</tr>
<tr>
<td><strong>보존용</strong></td>
<td><code>%rbx</code>, <code>%r12</code>~<code>%r15</code> 등</td>
<td>함수 호출 간 값을 유지해야 하는 레지스터들 (callee-saved)</td>
</tr>
</tbody></table>
<hr>
<h3 id="인자-전달-최대-6개까지-레지스터로">인자 전달 (최대 6개까지 레지스터로)</h3>
<p>함수에 인자를 넘길 때는 <strong>아래 순서대로 레지스터를 사용</strong>해:</p>
<table>
<thead>
<tr>
<th>인자 번호</th>
<th>레지스터</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td><code>%rdi</code></td>
</tr>
<tr>
<td>2</td>
<td><code>%rsi</code></td>
</tr>
<tr>
<td>3</td>
<td><code>%rdx</code></td>
</tr>
<tr>
<td>4</td>
<td><code>%rcx</code></td>
</tr>
<tr>
<td>5</td>
<td><code>%r8</code></td>
</tr>
<tr>
<td>6</td>
<td><code>%r9</code></td>
</tr>
<tr>
<td>7번 이상</td>
<td><strong>스택</strong>에 push 해서 전달함</td>
</tr>
</tbody></table>
<hr>
<h3 id="함수-리턴값은">함수 리턴값은?</h3>
<ul>
<li>리턴값은 기본적으로 <strong><code>%rax</code>에 저장</strong><ul>
<li>예: <code>return 42;</code> → <code>%rax = 42</code></li>
</ul>
</li>
<li>리턴값이 128비트 이상이면 다른 레지스터 추가 사용 or 메모리 통한 복잡한 처리 필요</li>
</ul>
<hr>
<h3 id="레지스터는-크게-두-종류">레지스터는 크게 두 종류</h3>
<table>
<thead>
<tr>
<th>구분</th>
<th>이름</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>Caller-saved</td>
<td><code>%rax</code>, <code>%rcx</code>, <code>%rdx</code>, <code>%rsi</code>, <code>%rdi</code>, <code>%r8</code>, <code>%r9</code>, <code>%r10</code>, <code>%r11</code></td>
<td>호출한 쪽이 백업해야 함</td>
</tr>
<tr>
<td>Callee-saved</td>
<td><code>%rbx</code>, <code>%rsp</code>, <code>%rbp</code>, <code>%r12</code>~<code>%r15</code></td>
<td>호출당한 함수가 백업해야 함 (<code>push</code>, <code>pop</code>)</td>
</tr>
</tbody></table>
<hr>
<h3 id="레지스터-버전별-비교-표">레지스터 버전별 비교 표</h3>
<table>
<thead>
<tr>
<th>크기</th>
<th>이름</th>
<th>비트수</th>
<th>예시</th>
</tr>
</thead>
<tbody><tr>
<td>64비트</td>
<td><code>%rdi</code>, <code>%rax</code>, ...</td>
<td>8바이트 (64bit)</td>
<td><code>movq</code>, <code>addq</code>, <code>callq</code> 등</td>
</tr>
<tr>
<td>32비트</td>
<td><code>%edi</code>, <code>%eax</code>, ...</td>
<td>4바이트 (32bit)</td>
<td><code>movl</code>, <code>addl</code></td>
</tr>
<tr>
<td>16비트</td>
<td><code>%di</code>, <code>%ax</code>, ...</td>
<td>2바이트 (16bit)</td>
<td><code>movw</code>, <code>addw</code></td>
</tr>
<tr>
<td>8비트</td>
<td><code>%dil</code>, <code>%al</code>, ...</td>
<td>1바이트 (8bit)</td>
<td><code>movb</code>, <code>addb</code></td>
</tr>
</tbody></table>
<hr>
<h3 id="rdi-edi-di-dil을-쓰는-상황"><code>%rdi</code>, <code>%edi</code>, <code>%di</code>, <code>%dil</code>을 쓰는 상황</h3>
<table>
<thead>
<tr>
<th>언제</th>
<th>어떤 크기?</th>
<th>어떤 이름?</th>
</tr>
</thead>
<tbody><tr>
<td>long, pointer, 64비트 정수</td>
<td>64비트</td>
<td><code>%rdi</code></td>
</tr>
<tr>
<td>int, 32비트 정수</td>
<td>32비트</td>
<td><code>%edi</code></td>
</tr>
<tr>
<td>short, 16비트 정수</td>
<td>16비트</td>
<td><code>%di</code></td>
</tr>
<tr>
<td>char, 8비트 정수</td>
<td>8비트</td>
<td><code>%dil</code></td>
</tr>
</tbody></table>
<p><strong>전달할 값의 크기(자료형)에 따라</strong> 자동으로 결정됨.</p>
<hr>
<h3 id="확장extension-계열"><strong>확장(extension)</strong> 계열</h3>
<ul>
<li><strong>작은 크기 → 큰 크기</strong>로 바꿀 때 사용</li>
<li>부호(sign)를 유지하느냐에 따라 구분됨</li>
</ul>
<table>
<thead>
<tr>
<th>명령어</th>
<th>뜻</th>
<th>비트 변환</th>
</tr>
</thead>
<tbody><tr>
<td><code>movsbl</code></td>
<td><strong>Sign-extend</strong> byte → long</td>
<td>8 → 32비트</td>
</tr>
<tr>
<td><code>movsbq</code></td>
<td>Sign-extend byte → quad</td>
<td>8 → 64비트</td>
</tr>
<tr>
<td><code>movswl</code></td>
<td>Sign-extend word (16) → long (32)</td>
<td>16 → 32비트</td>
</tr>
<tr>
<td><code>movswq</code></td>
<td>Sign-extend word (16) → quad (64)</td>
<td>16 → 64비트</td>
</tr>
<tr>
<td><code>movslq</code></td>
<td>Sign-extend long (32) → quad (64)</td>
<td>32 → 64비트</td>
</tr>
<tr>
<td><br></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>명령어</th>
<th>뜻</th>
<th>비트 변환</th>
</tr>
</thead>
<tbody><tr>
<td><code>movzbl</code></td>
<td><strong>Zero-extend</strong> byte → long</td>
<td>8 → 32비트</td>
</tr>
<tr>
<td><code>movzbq</code></td>
<td>Zero-extend byte → quad</td>
<td>8 → 64비트</td>
</tr>
<tr>
<td><code>movzwl</code></td>
<td>Zero-extend word → long</td>
<td>16 → 32비트</td>
</tr>
<tr>
<td><code>movzwq</code></td>
<td>Zero-extend word → quad</td>
<td>16 → 64비트</td>
</tr>
</tbody></table>
<hr>
<h3 id="igned-vs-unsigned-정수의-부호---유무">igned vs unsigned: 정수의 <strong>부호(+, -)</strong> 유무</h3>
<table>
<thead>
<tr>
<th>종류</th>
<th>부호 있음?</th>
<th>값의 범위 예 (8비트 기준)</th>
</tr>
</thead>
<tbody><tr>
<td><code>signed</code> (기본)</td>
<td>✅ 있음</td>
<td>-128 ~ +127</td>
</tr>
<tr>
<td><code>unsigned</code></td>
<td>❌ 없음</td>
<td>0 ~ 255</td>
</tr>
</tbody></table>
<hr>
<h3 id="x86-64-아키텍처-규칙">x86-64 아키텍처 규칙</h3>
<table>
<thead>
<tr>
<th>목적</th>
<th>명령어</th>
<th>결과 값 예</th>
</tr>
</thead>
<tbody><tr>
<td>char → int (32bit 부호 확장)</td>
<td><code>movsbl</code></td>
<td><code>0xFFFFFFFF</code></td>
</tr>
<tr>
<td>char → long (64bit 부호 확장)</td>
<td><code>movsbq</code></td>
<td><code>0xFFFFFFFFFFFFFFFF</code></td>
</tr>
<tr>
<td>char → long (64bit zero 확장)</td>
<td><code>movzbq</code></td>
<td><code>0x00000000000000FF</code></td>
</tr>
</tbody></table>
<hr>
<h3 id="자료형-변환-방향에-따른-동작-요약">자료형 변환 방향에 따른 동작 요약</h3>
<table>
<thead>
<tr>
<th>방향</th>
<th>동작</th>
<th>예시 명령어</th>
</tr>
</thead>
<tbody><tr>
<td>작은 → 큰 (<code>char → int</code>)</td>
<td>확장 필요 (sign/zero extend)</td>
<td><code>movsbl</code>, <code>movzbl</code> 등</td>
</tr>
<tr>
<td>큰 → 작은 (<code>int → char</code>)</td>
<td>잘라내기 (하위 비트만 사용)</td>
<td><code>movb %al, (%rsi)</code> 등</td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[트라이(Trie)]]></title>
            <link>https://velog.io/@jh_y/%ED%8A%B8%EB%9D%BC%EC%9D%B4Trie</link>
            <guid>https://velog.io/@jh_y/%ED%8A%B8%EB%9D%BC%EC%9D%B4Trie</guid>
            <pubDate>Tue, 01 Apr 2025 09:39:35 GMT</pubDate>
            <description><![CDATA[<blockquote>
</blockquote>
<h3 id="트라이란">트라이란?</h3>
<h4 id="--문자열을-효율적으로-처리하기-위한-트리-자료구조br">- 문자열을 효율적으로 처리하기 위한 트리 자료구조.<br></h4>
<p><img src="https://velog.velcdn.com/images/jh_y/post/6212a689-86cf-46cb-9b3e-35d8cee1b40d/image.png" alt=""><br></p>
<blockquote>
</blockquote>
<h3 id="단어의-끝에-도달했는지를-확인하는것이-중요">단어의 끝에 도달했는지를 확인하는것이 중요</h3>
<p><img src="https://velog.velcdn.com/images/jh_y/post/0f1a3a58-b9b2-4b0e-944b-3a01a46856b6/image.png" alt=""></p>
<blockquote>
</blockquote>
<h3 id="단어-제거">단어 제거</h3>
<h4 id="해당위치까지-찾아간다음-단어의-끝을-의미하는-것을-제거br정점-자체를-제거하면-안됨br--이전에-삽입한-정점들은-계속-메모리에-남아있어-메모리-측면에서-비효율적임br---그래서-삭제가-계속-발생하는-환경에서-트라이는-적합하지-않음">해당위치까지 찾아간다음 단어의 끝을 의미하는 것을 제거<br>**정점 자체를 제거하면 안됨<br>- 이전에 삽입한 정점들은 계속 메모리에 남아있어 메모리 측면에서 비효율적임<br> - 그래서 삭제가 계속 발생하는 환경에서 트라이는 적합하지 않음</h4>
<p><img src="https://velog.velcdn.com/images/jh_y/post/3550590f-a971-40c1-b8da-20e744993658/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[index( ) 함수]]></title>
            <link>https://velog.io/@jh_y/index-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@jh_y/index-%ED%95%A8%EC%88%98</guid>
            <pubDate>Tue, 01 Apr 2025 07:24:52 GMT</pubDate>
            <description><![CDATA[<h3 id="값의-인덱스-값-찾기">값의 인덱스 값 찾기</h3>
<blockquote>
</blockquote>
<pre><code class="language-python">a=[1,2,3,4,5]
#a 리스트에서 4의 위치(인덱스 값)을 찾는 코드
a.index(4) # 3</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Unpacking(구조 분해 할당)]]></title>
            <link>https://velog.io/@jh_y/Unpacking%EA%B5%AC%EC%A1%B0-%EB%B6%84%ED%95%B4-%ED%95%A0%EB%8B%B9</link>
            <guid>https://velog.io/@jh_y/Unpacking%EA%B5%AC%EC%A1%B0-%EB%B6%84%ED%95%B4-%ED%95%A0%EB%8B%B9</guid>
            <pubDate>Tue, 01 Apr 2025 02:54:56 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>리스트 slicer가 [값1, 값2, 값3] 형태일 때,
각 값을 순서대로 변수 a, b, c에 할당합니다.</p>
</blockquote>
<pre><code class="language-python">slicer = [2, 5, 10]
a, b, c = slicer
print(a)  # 2
print(b)  # 5
print(c)  # 10</code></pre>
<h3 id="주의할-점">주의할 점</h3>
<p><strong>slicer의 길이가 반드시 3이어야</strong> 해요.
만약 <code>[1, 2]</code>처럼 2개만 있으면 에러 발생:</p>
<pre><code class="language-python">a, b, c = [1, 2]
# ValueError: not enough values to unpack (expected 3, got 2)
</code></pre>
<p>반대로 4개 이상이면?</p>
<pre><code class="language-python">a, b, c = [1, 2, 3, 4]
# ValueError: too many values to unpack (expected 3)
</code></pre>
<hr>
<h3 id="안전하게-언패킹하려면">안전하게 언패킹하려면?</h3>
<ul>
<li>갯수가 다를 수 있다면 <strong>슬라이싱</strong>이나 <strong>별표(*) 연산자</strong>를 써서 처리 가능:</li>
</ul>
<pre><code class="language-python">a, b, *rest = [1, 2, 3, 4, 5]
# a = 1, b = 2, rest = [3, 4, 5]
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[다익스트라]]></title>
            <link>https://velog.io/@jh_y/%EB%8B%A4%EC%9D%B5%EC%8A%A4%ED%8A%B8%EB%9D%BC</link>
            <guid>https://velog.io/@jh_y/%EB%8B%A4%EC%9D%B5%EC%8A%A4%ED%8A%B8%EB%9D%BC</guid>
            <pubDate>Mon, 31 Mar 2025 16:22:58 GMT</pubDate>
            <description><![CDATA[<h3 id="다익스트라-알고리즘-방향-무방향-그래프에서---br---하나의-시작점으로부터-다른-모든-정점까지의-최단-거리를-구하는-알고리즘br--기능은-플로이드가-더-좋음-br--플로이드는-음수인-간선이-있는건-상관이-없고-음수인-사이클이-있을때-문제발생br--다익스트라는-음수의-가중치를-가지는-간선이-있으면-아예-사용-불가">다익스트라 알고리즘( 방향, 무방향 그래프에서 )  <br>-  하나의 시작점으로부터 다른 모든 정점까지의 최단 거리를 구하는 알고리즘<br>- 기능은 플로이드가 더 좋음. <br>- 플로이드는 음수인 간선이 있는건 상관이 없고 음수인 사이클이 있을때 문제발생.<br>- 다익스트라는 음수의 가중치를 가지는 간선이 있으면 아예 사용 불가.</h3>
<p><img src="https://velog.velcdn.com/images/jh_y/post/7f6e3ff9-9010-4294-8e93-782a6f515919/image.png" alt=""></p>
<h3 id="풀이-방법">풀이 방법</h3>
<p><img src="https://velog.velcdn.com/images/jh_y/post/4ed9fe14-89fd-44ca-83df-ec432e365799/image.png" alt=""></p>
<blockquote>
<h4 id="자기-자신과의-거리는-0이므로-1번-인덱스의-값은-0이다br인접한-정점-중-가장-가까운-가중치가-작은-정점을-최단-거리-테이블에-넣어-확정시킨다">자기 자신과의 거리는 0이므로 1번 인덱스의 값은 0이다.<br>인접한 정점 중 가장 가까운, 가중치가 작은 정점을 최단 거리 테이블에 넣어 확정시킨다.</h4>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jh_y/post/971acf8e-c3b9-46c1-90fc-b53d996b0ffd/image.png" alt=""></p>
<blockquote>
</blockquote>
<h3 id="우선순위-큐를-이용한-다익스트라-알고리즘">우선순위 큐를 이용한 다익스트라 알고리즘!</h3>
<p><img src="https://velog.velcdn.com/images/jh_y/post/f8d4442e-0e19-4896-8e95-aa3d73828afc/image.png" alt=""></p>
<h4 id="1-우선순위-큐에-0-시작점을-추가br2-우선순위-큐에서-거리가-가장-작은-원소를-선택-해당-거리가-최단-거리-테이블에-있는-값과-다를-경우-넘어감br3-원소가-가리키는-정점을-v라고-할-때-v와-이웃한-정점들에-대해-최단-거리-테이블-값보다-v를-거쳐가는-것이-더-작은-값을-가질-경우-최단-거리-테이블의-값을-갱신하고-우선순위-큐에-거리-이웃한-정점의-번호를-추가br4-우선순위-큐가-빌-때-까지-2-3번-과정을-반복">1. 우선순위 큐에 (0, 시작점)을 추가.<br>2. 우선순위 큐에서 거리가 가장 작은 원소를 선택, 해당 거리가 최단 거리 테이블에 있는 값과 다를 경우 넘어감.<br>3. 원소가 가리키는 정점을 v라고 할 때, v와 이웃한 정점들에 대해 최단 거리 테이블 값보다 v를 거쳐가는 것이 더 작은 값을 가질 경우 최단 거리 테이블의 값을 갱신하고 우선순위 큐에 (거리, 이웃한 정점의 번호)를 추가.<br>4. 우선순위 큐가 빌 때 까지 2, 3번 과정을 반복.<img src="https://velog.velcdn.com/images/jh_y/post/8296cc4b-7869-4662-b16a-dfdf7a3683a2/image.png" alt=""></h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[플로이드]]></title>
            <link>https://velog.io/@jh_y/%ED%94%8C%EB%A1%9C%EC%9D%B4%EB%93%9C</link>
            <guid>https://velog.io/@jh_y/%ED%94%8C%EB%A1%9C%EC%9D%B4%EB%93%9C</guid>
            <pubDate>Mon, 31 Mar 2025 16:03:11 GMT</pubDate>
            <description><![CDATA[<h3 id="플로이드-알고리즘--모든-정점-쌍-사이의-최단-거리를-구하는-알고리즘">플로이드 알고리즘 = 모든 정점 쌍 사이의 최단 거리를 구하는 알고리즘</h3>
<p><img src="https://velog.velcdn.com/images/jh_y/post/6140106e-b0dd-4c47-b230-5dec79d53204/image.png" alt=""></p>
<h4 id="--방향-무방향-둘다-가능br--간선값이-음수여도-동작-but-음수인-사이클이-있으면-문제-발생br--자기-자신으로-가는거리--0--간선-1개로-바로-건너갈-수-있는-곳--간선의-값brbr접근법br--현재-테이블에서-1번을-거쳐가는-최단-거리만을-먼저-갱신br--다른-모든-경우도-모두-계산-최종적인-최단-거리까지-구현brbr시간복잡도br--ov3">- 방향, 무방향 둘다 가능<br>- 간선값이 음수여도 동작. but 음수인 사이클이 있으면 문제 발생.<br>- 자기 자신으로 가는거리 = 0 , 간선 1개로 바로 건너갈 수 있는 곳 = 간선의 값<br><br>접근법<br>- 현재 테이블에서 1번을 거쳐가는 최단 거리만을 먼저 갱신<br>- 다른 모든 경우도 모두 계산. 최종적인 최단 거리까지 구현<br><br>시간복잡도<br>- O(V^3)</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[위상정렬]]></title>
            <link>https://velog.io/@jh_y/%EC%9C%84%EC%83%81%EC%A0%95%EB%A0%AC</link>
            <guid>https://velog.io/@jh_y/%EC%9C%84%EC%83%81%EC%A0%95%EB%A0%AC</guid>
            <pubDate>Mon, 31 Mar 2025 15:26:30 GMT</pubDate>
            <description><![CDATA[<blockquote>
</blockquote>
<h3 id="위상정렬-이란br">위상정렬 이란<br></h3>
<p><img src="https://velog.velcdn.com/images/jh_y/post/f45826eb-d180-452c-be05-5baad9d43b18/image.png" alt=""></p>
<h5 id="올바른-위상정렬br--abcdefbr--acedbfbr--badcefbr--badfcebrbr올바르지-않은-위상정렬br--bfaced는-f가-d보다-먼저-나오기-때문에-잘못된-위상정렬이다-brbr자신보다-앞에-위치하는-정점이-없어야한다br자신에게-들어오는-간선이-없어야한다brindegree---자신에게-들어오는-간선의-수br">올바른 위상정렬<br>- ABCDEF<br>- ACEDBF<br>- BADCEF<br>- BADFCE<br><br>올바르지 않은 위상정렬<br>- BFACED는 F가 D보다 먼저 나오기 때문에 잘못된 위상정렬이다. <br><br><strong>자신보다 앞에 위치하는 정점이 없어야한다.<br>자신에게 들어오는 간선이 없어야한다.<br>indegree - 자신에게 들어오는 간선의 수</strong><br></h5>
<blockquote>
</blockquote>
<h3 id="br위상정렬-알고리즘"><br>위상정렬 알고리즘</h3>
<h4 id="1맨-처음-모든-간선을-읽으며-indegree-테이블을-채움br2indegree가-0인-정점들을-모두-큐에-넣음br3큐에서-정점을-꺼내어-위상-정렬-결과에-추가br4해당-정점으로부터-연결된-모든-정점의-indegree-값을-1-감소시킴-이-때-indegree가-0이-되었다면-그-정점을-큐에-추가br5큐가-빌-때-까지-34번-과정을-반복">1.맨 처음 모든 간선을 읽으며 indegree 테이블을 채움<br>2.indegree가 0인 정점들을 모두 큐에 넣음<br>3.큐에서 정점을 꺼내어 위상 정렬 결과에 추가<br>4.해당 정점으로부터 연결된 모든 정점의 indegree 값을 1 감소시킴 이 때 indegree가 0이 되었다면 그 정점을 큐에 추가<br>5.큐가 빌 때 까지 3,4번 과정을 반복</h4>
<blockquote>
<p><img src="https://velog.velcdn.com/images/jh_y/post/4bad5a46-2dbc-48c4-a192-8bbcc9093b36/image.png" alt=""><img src="https://velog.velcdn.com/images/jh_y/post/d2bca978-de4c-4500-9d9f-91ec16eea102/image.png" alt=""><img src="https://velog.velcdn.com/images/jh_y/post/db3b692e-e188-4d91-a5a4-8cf130071a41/image.png" alt=""></p>
</blockquote>
<blockquote>
</blockquote>
<h3 id="위상정렬은-사이클이-존재하면-모순이-발생">위상정렬은 사이클이 존재하면 모순이 발생</h3>
<p><img src="https://velog.velcdn.com/images/jh_y/post/f23a866e-0480-4fae-aac6-4856305d6607/image.png" alt=""></p>
<h5 id="a-b-c-중-어느것이-먼저-나오더라도순서와-상관없이-br간선으로-주어진-정점-간-선후관계에-모순이-발생한다br위상정렬은-사이클이-존재하지-않는-방향-그래프에서만-잘-정의된다brdagdirected-acyclic-fraph---사이클이-존재하지-않는-방향그래프">A, B, C 중 어느것이 먼저 나오더라도(순서와 상관없이) <br>간선으로 주어진 정점 간 선후관계에 모순이 발생한다.<br>위상정렬은 사이클이 존재하지 않는 방향 그래프에서만 잘 정의된다.<br><strong>DAG(Directed Acyclic Fraph)</strong> - 사이클이 존재하지 않는 방향그래프</h5>
]]></description>
        </item>
        <item>
            <title><![CDATA[리스트 (BFS),(DFS)]]></title>
            <link>https://velog.io/@jh_y/%EB%A6%AC%EC%8A%A4%ED%8A%B8-BFSDFS</link>
            <guid>https://velog.io/@jh_y/%EB%A6%AC%EC%8A%A4%ED%8A%B8-BFSDFS</guid>
            <pubDate>Mon, 31 Mar 2025 05:01:49 GMT</pubDate>
            <description><![CDATA[<h3 id="bfs-너비-우선-탐색-큐">BFS (너비 우선 탐색), (큐)</h3>
<p><img src="https://velog.velcdn.com/images/jh_y/post/001e1926-9a3d-48c9-897d-ebff5268252b/image.png" alt=""></p>
<blockquote>
</blockquote>
<ol>
<li>처음에 1을 큐에 넣고 방문했다는 표시 남김</li>
<li>큐가 비어있지 않으니 큐의 front인 1번 정점을 꺼낸다</li>
<li>1번 정점과 이웃한 2, 3, 4번 정점은 방문하지 않은 정점이라 큐에 순서대로 넣고 방문처리.</li>
<li>큐가 비어있지 않으니 순서대로 큐의 front정점을 꺼냄</li>
<li>2번은 주변에 방문하지 않은 정점이 없지만 3번은 방문하지 않은 정점 5번을 이웃하고 있어 5번을 큐에 넣고 방문했다는 표시 남김</li>
<li>큐가 비어있을 때 까지 반복</li>
</ol>
<p><img src="https://velog.velcdn.com/images/jh_y/post/48bdaa99-7e6c-440a-b244-9d819a9bb17c/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jh_y/post/791f6fae-42be-47e0-9c65-d11a28087eb6/image.png" alt=""></p>
<h3 id="if-연결그래프가-아닐때-bfs순회를-하려면">if 연결그래프가 아닐때 BFS순회를 하려면?</h3>
<p>for문을 돌면서 아직 방문하지 않은 정점을 찾아 그 정점을 시작정점으로 잡게 코드를 구현하면 된다.</p>
<h3 id="가중치">가중치</h3>
<p>모든 간선의 길이가 동일한 상황에서 두 지점 사이의 거리를 찾는 문제는 BFS로 처리 가능.
BUT. 모든 간선의 길이가 다르다면 플로이드나 다익스트라와 같은 알고리즘 사용.</p>
<h3 id="dfs깊이-우선-탐색-스택">DFS(깊이 우선 탐색), (스택)</h3>
<p>간단하다. BFS과정에서 큐를 스택으로만 변경하면 끝
<br>재귀가 가능하다. 재귀적으로 함수를 호출하는 상황 = 가장 늦게 호출된 함수를 차례대로 처리. LIFO (스택) but, 재귀로 구현할 때 깊이가 깊어지면 문제가 생길 수 있다.
<img src="https://velog.velcdn.com/images/jh_y/post/b114ebf2-2a7e-478e-bd34-d9dde1db1003/image.png" alt="">
재귀로 처리하면 실제 방문을 할 때 방문표시를 남긴다.
비재귀적인 방식은 방문하기 전에 방문하지 않은 곳을 발견하면 그 때 방문 표시를 남긴다.
<strong>강조</strong>
비재귀 DFS는 순회를 잘 수행하지만 엄밀히 말해 우리가 관념적으로 생각하는 DFS와는 방문순서가 다르다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[try ~ except]]></title>
            <link>https://velog.io/@jh_y/try-except</link>
            <guid>https://velog.io/@jh_y/try-except</guid>
            <pubDate>Sun, 30 Mar 2025 23:09:08 GMT</pubDate>
            <description><![CDATA[<h4 id="기본-구조">기본 구조</h4>
<pre><code class="language-python">try:
    실행할 코드
except 예외타입:
    예외 발생 시 실행할 코드</code></pre>
<h4 id="beakjoon-5639-코드에서의-역할">beakjoon 5639 코드에서의 역할</h4>
<pre><code class="language-python">pre = []
while True:
    try:
        pre.append(int(sys.stdin.readline()))
    except:
        break
</code></pre>
<h4 id="이-코드의-의미">이 코드의 의미</h4>
<ul>
<li><code>sys.stdin.readline()</code>은 줄 단위로 입력을 받습니다.</li>
<li>입력이 끝나면(EOF: End Of File) <code>int(...)</code>에서 <strong>오류(Exception)</strong>가 발생합니다.</li>
<li>그때 <code>except</code> 블록으로 빠져서 <code>while</code> 루프를 멈추게 됩니다.</li>
</ul>
<h4 id="쓰이는-이유">쓰이는 이유</h4>
<blockquote>
<p>입력 개수가 정해져 있지 않은 경우 (EOF 입력 방식)에는
<code>try ~ except</code>를 사용해서 입력이 끝나는 시점을 처리.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[3/30]]></title>
            <link>https://velog.io/@jh_y/330</link>
            <guid>https://velog.io/@jh_y/330</guid>
            <pubDate>Sun, 30 Mar 2025 14:42:55 GMT</pubDate>
            <description><![CDATA[<h3 id="문자열-추가">문자열 추가</h3>
<p>문자열.append()는 쓸 수 없음.
리스트.append()는 가능</p>
<p>문자열은 </p>
<blockquote>
<p>문자열 += 추가할 str</p>
</blockquote>
<h3 id="문자열뒤집기슬라이싱">문자열뒤집기(슬라이싱)</h3>
<blockquote>
</blockquote>
<pre><code>a[i:j+1][::-1]</code></pre><ul>
<li>start &lt; end일 때: step은 양수여야 함 (왼쪽 → 오른쪽)</li>
<li>start &gt; end일 때: step은 음수여야 함 (오른쪽 → 왼쪽)</li>
<li>슬라이싱은 항상 start부터 end 전까지입니다</li>
</ul>
<h3 id="그런데-이걸-aij1-1로-쓰면">그런데 이걸 <code>a[i:j+1:-1]</code>로 쓰면?</h3>
<pre><code class="language-python">a = [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;, &#39;e&#39;]
a[1:4][::-1]    # ✅ [&#39;d&#39;, &#39;c&#39;, &#39;b&#39;]
a[1:4:-1]       # ❌ []  (결과 없음)
</code></pre>
<p>왜냐면 <code>start=1</code>, <code>end=4</code>, <code>step=-1</code>은
<strong>왼쪽부터 오른쪽 방향인데 역순(-1)</strong> 이라 <strong>조건 충돌</strong>이 생깁니다.</p>
<p>파이썬은 이런 경우 &quot;읽을 수 있는 방향이 아예 없음&quot;으로 보고 빈 리스트를 반환.</p>
<h3 id="join">join()</h3>
<blockquote>
</blockquote>
<pre><code>&#39;&#39;.join(리스트)</code></pre><p>리스트를 하나의 문자열로 만들어준다.
join은 문자열 리스트에만 사용</p>
<hr>
<h3 id="각-문자열-슬라이스로-이어붙이기">각 문자열 슬라이스로 이어붙이기</h3>
<blockquote>
</blockquote>
<pre><code class="language-python">def solution(my_strings, parts):
    answer = &#39;&#39;
    for i in range(len(my_strings)):
        s, e = parts[i]
        answer += my_strings[i][s:e+1]
    return answer</code></pre>
<ul>
<li><code>my_strings[i][s:e+1]</code> → <strong>끝 인덱스를 포함하기 위해 <code>e+1</code></strong></li>
<li><code>answer</code>에 차례대로 잘라붙임</li>
</ul>
<h3 id="리스트안에-값-확인하는-방법">리스트안에 값 확인하는 방법</h3>
<blockquote>
</blockquote>
<pre><code class="language-python">if is_suffix in a:</code></pre>
<p>a 리스트안에 is_suffix가 있으면 True</p>
<h3 id="startswith-란">startswith 란?</h3>
<blockquote>
</blockquote>
<pre><code class="language-python">str.startswith(prefix)</code></pre>
<p>반환값</p>
<ul>
<li>시작하면 True</li>
<li>아니면 False<pre><code class="language-python">ex)
s = &quot;hello&quot;
s.startswith(&quot;he&quot;)     # True
s.startswith(&quot;x&quot;)      # False</code></pre>
<pre><code>(시작 위치 지정)
&quot;abcdef&quot;.startswith(&quot;c&quot;, 2)  # True</code></pre></li>
</ul>
<h3 id="1-ord-와-chr">1. <code>ord()</code> 와 <code>chr()</code></h3>
<table>
<thead>
<tr>
<th>함수</th>
<th>설명</th>
<th>예시</th>
</tr>
</thead>
<tbody><tr>
<td><code>ord(&#39;A&#39;)</code></td>
<td>문자를 아스키 코드로</td>
<td><code>65</code></td>
</tr>
<tr>
<td><code>chr(65)</code></td>
<td>아스키 코드를 문자로</td>
<td><code>&#39;A&#39;</code></td>
</tr>
</tbody></table>
<p>```python
for i in range(26):
    chr(ord(&#39;A&#39;) + i)  # A~Z 생성</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[class(__init__, self, super)]]></title>
            <link>https://velog.io/@jh_y/classinit-self-super</link>
            <guid>https://velog.io/@jh_y/classinit-self-super</guid>
            <pubDate>Sun, 30 Mar 2025 14:02:10 GMT</pubDate>
            <description><![CDATA[<h3 id="클래스란">클래스란?</h3>
<ul>
<li>객체(Object)를 생성하기 위한 <strong>틀(Template)</strong></li>
<li>변수(속성)와 함수(메서드)를 <strong>묶어서 하나의 구조로 정의</strong></li>
</ul>
<pre><code class="language-python">class ClassName:
    def method(self):
        pass
</code></pre>
<hr>
<h3 id="생성자-__init__">생성자 <code>__init__()</code></h3>
<table>
<thead>
<tr>
<th>항목</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>역할</td>
<td>객체 생성 시 자동 호출되는 함수</td>
</tr>
<tr>
<td>목적</td>
<td>인스턴스 변수 초기화 (초기 세팅)</td>
</tr>
</tbody></table>
<pre><code class="language-python">class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age</code></pre>
<ul>
<li><strong>init</strong> 함수는 클래스를 선언하는순간 실행이 된다.</li>
<li>객체가 생성될 때 실행됨</li>
<li><code>__init__()</code> 안의 <code>self.name</code>은 객체의 속성, <code>name</code>은 전달된 값</li>
</ul>
<hr>
<h3 id="self">self</h3>
<table>
<thead>
<tr>
<th>항목</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>의미</td>
<td>인스턴스 자기 자신을 가리킴</td>
</tr>
<tr>
<td>용도</td>
<td>인스턴스의 변수/메서드에 접근할 때 사용</td>
</tr>
</tbody></table>
<pre><code class="language-python">def set_name(self, name):
    self.name = name
</code></pre>
<ul>
<li>메서드는 항상 <code>self</code>를 첫 번째 인자로 가짐</li>
<li><code>self.name</code>: 인스턴스 변수에 접근</li>
</ul>
<hr>
<h3 id="상속과-super">상속과 super()</h3>
<table>
<thead>
<tr>
<th>항목</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>super()</td>
<td>부모 클래스의 메서드 호출 시 사용</td>
</tr>
<tr>
<td>용도</td>
<td>부모 클래스의 생성자나 메서드를 자식 클래스에서 호출</td>
</tr>
</tbody></table>
<pre><code class="language-python">class Animal:
    def __init__(self, name):
        self.name = name

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)  # 부모 생성자 호출
        self.breed = breed
</code></pre>
<ul>
<li><code>super()</code>는 부모 클래스에 접근할 때 사용</li>
<li>중복 제거 및 유지보수 용이</li>
</ul>
<hr>
<h3 id="클래스-예시-전체">클래스 예시 전체</h3>
<pre><code class="language-python">class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        print(f&quot;{self.name}가 소리를 냅니다&quot;)

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)
        self.breed = breed

    def speak(self):
        print(f&quot;{self.name}는 멍멍 짖어요 ({self.breed})&quot;)

dog1 = Dog(&quot;초코&quot;, &quot;푸들&quot;)
dog1.speak()
</code></pre>
<blockquote>
</blockquote>
<p><strong>출력 결과</strong></p>
<pre><code>초코는 멍멍 짖어요 (푸들)</code></pre><hr>
<h3 id="핵심-요약">핵심 요약</h3>
<table>
<thead>
<tr>
<th>키워드</th>
<th>의미</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>class</td>
<td>클래스 정의 키워드</td>
<td>틀(template)을 만들기 위함</td>
</tr>
<tr>
<td><strong>init</strong></td>
<td>생성자 메서드</td>
<td>객체 생성 시 자동 호출</td>
</tr>
<tr>
<td>self</td>
<td>자기 객체 참조</td>
<td>인스턴스의 속성 접근용</td>
</tr>
<tr>
<td>super()</td>
<td>부모 클래스 참조</td>
<td>부모 메서드 호출용</td>
</tr>
</tbody></table>
<hr>
<h3 id="자주-나오는-문법-요약">자주 나오는 문법 요약</h3>
<table>
<thead>
<tr>
<th>문법</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>obj = ClassName()</code></td>
<td>클래스 인스턴스 생성</td>
</tr>
<tr>
<td><code>self.attr = val</code></td>
<td>객체 내부에 속성 저장</td>
</tr>
<tr>
<td><code>super().__init__()</code></td>
<td>부모 클래스 생성자 호출</td>
</tr>
<tr>
<td><code>클래스 상속</code></td>
<td><code>class SubClass(ParentClass):</code></td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[count() vs collections.Counter]]></title>
            <link>https://velog.io/@jh_y/count-vs-collections.Counter</link>
            <guid>https://velog.io/@jh_y/count-vs-collections.Counter</guid>
            <pubDate>Sun, 30 Mar 2025 13:47:00 GMT</pubDate>
            <description><![CDATA[<h3 id="개념-비교">개념 비교</h3>
<table>
<thead>
<tr>
<th>항목</th>
<th><code>count()</code></th>
<th><code>collections.Counter</code></th>
</tr>
</thead>
<tbody><tr>
<td>기본 용도</td>
<td><strong>특정 값 1개의 등장 횟수</strong> 확인</td>
<td><strong>모든 값의 빈도수</strong>를 딕셔너리 형태로 계산</td>
</tr>
<tr>
<td>반환값</td>
<td>정수(int)</td>
<td>딕셔너리(dict) 형태의 객체</td>
</tr>
<tr>
<td>자료형</td>
<td>문자열, 리스트 등 반복 가능한 객체</td>
<td>문자열, 리스트 등 반복 가능한 객체</td>
</tr>
<tr>
<td>속도</td>
<td>특정 값 1개만 셀 때 빠름</td>
<td>전체 값의 빈도 분석에 유리</td>
</tr>
</tbody></table>
<hr>
<h3 id="사용법">사용법</h3>
<h4 id="count--특정-값만-세기"><code>count()</code> – 특정 값만 세기</h4>
<pre><code class="language-python">s = &quot;banana&quot;
s.count(&#39;a&#39;)     # 3
</code></pre>
<h3 id="collectionscounter--전체-빈도수-분석"><code>collections.Counter</code> – 전체 빈도수 분석</h3>
<pre><code class="language-python">from collections import Counter

s = &quot;banana&quot;
Counter(s)
# 출력: Counter({&#39;a&#39;: 3, &#39;n&#39;: 2, &#39;b&#39;: 1})
</code></pre>
<hr>
<h3 id="리스트-예시">리스트 예시</h3>
<pre><code class="language-python">lst = [1, 2, 2, 3, 1, 1, 2]

# count()
lst.count(2)     # 3

# Counter
from collections import Counter
Counter(lst)
# 출력: Counter({1: 3, 2: 3, 3: 1})
</code></pre>
<hr>
<h3 id="주요-차이-요약">주요 차이 요약</h3>
<table>
<thead>
<tr>
<th>비교 항목</th>
<th><code>count()</code></th>
<th><code>Counter()</code></th>
</tr>
</thead>
<tbody><tr>
<td>특정 값만 확인</td>
<td>O</td>
<td>O</td>
</tr>
<tr>
<td>전체 빈도 분석</td>
<td>X</td>
<td>O</td>
</tr>
<tr>
<td>반환 형태</td>
<td>정수 (int)</td>
<td>딕셔너리 유사 객체</td>
</tr>
<tr>
<td>활용 예시</td>
<td><code>&#39;a&#39; 가 몇 번 나왔는지</code></td>
<td>전체 알파벳/숫자의 등장 횟수</td>
</tr>
</tbody></table>
<hr>
<h3 id="counter-응용-팁">Counter 응용 팁</h3>
<pre><code class="language-python"># 가장 많이 등장한 요소 n개 구하기
Counter(&quot;banana&quot;).most_common(1)
# 결과: [(&#39;a&#39;, 3)]
</code></pre>
<pre><code class="language-python"># 딕셔너리처럼 사용
c = Counter(&quot;banana&quot;)
c[&#39;a&#39;]     # 3
c[&#39;z&#39;]     # 0 (없는 값도 기본 0 반환)
</code></pre>
<hr>
<h2 id="핵심-요약">핵심 요약</h2>
<ul>
<li><strong><code>count()</code></strong>: 특정 원소의 개수만 셀 때 간편하게 사용</li>
<li><strong><code>Counter</code></strong>: 모든 원소의 빈도수를 한 번에 분석할 때 유리</li>
<li>문자열, 리스트, 튜플 등 반복 가능한 자료형 모두 사용 가능</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[사이클 판별 - 간선 기반 사이클 탐지]]></title>
            <link>https://velog.io/@jh_y/%EC%82%AC%EC%9D%B4%ED%81%B4-%ED%8C%90%EB%B3%84-%EA%B0%84%EC%84%A0-%EA%B8%B0%EB%B0%98-%EC%82%AC%EC%9D%B4%ED%81%B4-%ED%83%90%EC%A7%80</link>
            <guid>https://velog.io/@jh_y/%EC%82%AC%EC%9D%B4%ED%81%B4-%ED%8C%90%EB%B3%84-%EA%B0%84%EC%84%A0-%EA%B8%B0%EB%B0%98-%EC%82%AC%EC%9D%B4%ED%81%B4-%ED%83%90%EC%A7%80</guid>
            <pubDate>Sun, 30 Mar 2025 07:25:02 GMT</pubDate>
            <description><![CDATA[<h3 id="개념-요약">개념 요약</h3>
<ul>
<li><strong>그래프에서 사이클이 생기는지 판단하는 방법</strong></li>
<li>특히 <strong>MST 문제(최소 신장 트리)</strong> 에서 필수 개념</li>
<li><strong>간선을 하나씩 추가할 때</strong>, <strong>사이클을 유발하는지 실시간 판별해야 함</strong></li>
</ul>
<hr>
<h3 id="유니온-파인드-disjoint-set-union---dsu">유니온 파인드 (Disjoint Set Union - DSU)</h3>
<h4 id="핵심-원리">핵심 원리</h4>
<ul>
<li><strong>두 정점이 같은 집합에 속해 있다면 → 사이클 발생</strong></li>
<li>새로운 간선을 추가할 때마다 <code>find()</code>로 대표 노드 비교</li>
</ul>
<h4 id="구현-방식">구현 방식</h4>
<pre><code class="language-python"># 기본적인 유니온 파인드 구조
parent = [i for i in range(n + 1)]

def find(x):
    if parent[x] != x:
        parent[x] = find(parent[x])  # 경로 압축
    return parent[x]

def union(a, b):
    a_root = find(a)
    b_root = find(b)
    if a_root &lt; b_root:
        parent[b_root] = a_root
    else:
        parent[a_root] = b_root
</code></pre>
<h4 id="사이클-판별-코드">사이클 판별 코드</h4>
<pre><code class="language-python">if find(a) == find(b):
    # 사이클 발생
    pass
else:
    union(a, b)
</code></pre>
<table>
<thead>
<tr>
<th>항목</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>시간 복잡도</td>
<td>거의 O(1) (경로 압축 시)</td>
</tr>
<tr>
<td>특징</td>
<td>빠르고 실전 최적화</td>
</tr>
<tr>
<td>사용 예</td>
<td>크루스칼 알고리즘에서 사이클 판단 핵심</td>
</tr>
</tbody></table>
<hr>
<h3 id="dfsbfs로-사이클-판별">DFS/BFS로 사이클 판별</h3>
<h4 id="설명">설명</h4>
<ul>
<li><p><strong>현재 간선 (a, b)</strong> 를 추가하기 전에</p>
<p>  <strong>a에서 b로 이미 경로가 있는지 탐색</strong> → 있다면 사이클</p>
</li>
<li><p>이론적으로 가능하지만, 실전에서는 비효율</p>
</li>
</ul>
<table>
<thead>
<tr>
<th>항목</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>시간 복잡도</td>
<td>O(V + E) * 간선 수</td>
</tr>
<tr>
<td>사용 예</td>
<td>DFS로 사이클 찾기 문제 전용</td>
</tr>
<tr>
<td>실전 MST 문제</td>
<td>비추 (느림, 반복 탐색 필요)</td>
</tr>
</tbody></table>
<hr>
<h3 id="방법-비교-요약">방법 비교 요약</h3>
<table>
<thead>
<tr>
<th>방법</th>
<th>특징</th>
<th>시간 복잡도</th>
<th>MST 문제 적합도</th>
</tr>
</thead>
<tbody><tr>
<td>유니온 파인드</td>
<td>집합 비교만으로 즉시 판단</td>
<td>거의 O(1)</td>
<td>✅ 매우 적합</td>
</tr>
<tr>
<td>DFS/BFS</td>
<td>경로를 직접 탐색</td>
<td>O(V + E)</td>
<td>❌ 비효율적</td>
</tr>
</tbody></table>
<hr>
<h3 id="결론">결론</h3>
<ul>
<li><strong>MST 문제에서는 무조건 유니온 파인드 사용</strong></li>
<li>DFS/BFS는 이론적으로만 가능하며 <strong>실전에서는 사용하지 않음</strong></li>
<li><strong>크루스칼 알고리즘 = 간선 정렬 + 유니온 파인드</strong></li>
</ul>
<hr>
<h3 id="참고-프림-알고리즘의-사이클-처리">참고: 프림 알고리즘의 사이클 처리</h3>
<ul>
<li><strong>Prim 알고리즘은 사이클을 체크하지 않음</strong></li>
<li>대신, <strong>방문 여부</strong>만으로 새로운 정점을 선택</li>
<li>구조적으로 사이클이 생기지 않도록 설계되어 있음</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[DFS (Depth-First Search)]]></title>
            <link>https://velog.io/@jh_y/DFS-Depth-First-Search</link>
            <guid>https://velog.io/@jh_y/DFS-Depth-First-Search</guid>
            <pubDate>Sun, 30 Mar 2025 07:17:09 GMT</pubDate>
            <description><![CDATA[<h3 id="dfs란">DFS란?</h3>
<ul>
<li>DFS는 그래프의 <strong>가장 깊은 정점까지 탐색한 뒤</strong>, 더 이상 갈 곳이 없으면 <strong>되돌아오는(Backtracking)</strong> 방식</li>
<li><strong>스택(Stack)</strong> 또는 <strong>재귀(Recursive Function)</strong> 로 구현</li>
<li>보통 <strong>경로 기반의 완전탐색, 백트래킹, 사이클 탐지 등</strong>에 사용</li>
</ul>
<hr>
<h3 id="언제-사용되는가">언제 사용되는가?</h3>
<table>
<thead>
<tr>
<th>목적</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>모든 경로 탐색</td>
<td>깊이 기반 경로 탐색, 경우의 수 확인</td>
</tr>
<tr>
<td>백트래킹</td>
<td>조합, 순열 등 조건 분기 탐색</td>
</tr>
<tr>
<td>연결 요소 찾기</td>
<td>그래프에서 떨어진 컴포넌트 찾기</td>
</tr>
<tr>
<td>사이클 탐지</td>
<td>순환 경로 유무 판별</td>
</tr>
<tr>
<td>조합/순열 생성</td>
<td>DFS + 조건 분기로 구현 가능</td>
</tr>
</tbody></table>
<hr>
<h3 id="동작-방식">동작 방식</h3>
<ol>
<li>시작 노드를 방문하고 처리</li>
<li>방문한 노드에서 인접한 노드로 이동</li>
<li>더 이상 방문할 곳이 없을 때까지 반복</li>
<li>더 이상 진행 불가하면 되돌아가서 다른 분기로 이동</li>
</ol>
<hr>
<h3 id="구현-예시-python">구현 예시 (Python)</h3>
<h4 id="재귀-함수-방식">재귀 함수 방식</h4>
<pre><code class="language-python">def dfs(graph, v, visited):
    visited[v] = True
    print(v, end=&#39; &#39;)

    for neighbor in graph[v]:
        if not visited[neighbor]:
            dfs(graph, neighbor, visited)
</code></pre>
<pre><code class="language-python">graph = [
    [],         # 0번 노드 미사용
    [2, 3],     # 1번 → 2, 3
    [4],
    [4],
    [],
]
visited = [False] * 5
dfs(graph, 1, visited)  # 출력: 1 2 4 3
</code></pre>
<hr>
<h4 id="스택-기반-반복문-방식-재귀-없이">스택 기반 반복문 방식 (재귀 없이)</h4>
<pre><code class="language-python">def dfs_stack(graph, start):
    visited = [False] * len(graph)
    stack = [start]

    while stack:
        v = stack.pop()
        if not visited[v]:
            visited[v] = True
            print(v, end=&#39; &#39;)
            stack.extend(reversed(graph[v]))  # 순서 보장
</code></pre>
<hr>
<h3 id="시간-복잡도">시간 복잡도</h3>
<table>
<thead>
<tr>
<th>항목</th>
<th>시간 복잡도</th>
</tr>
</thead>
<tbody><tr>
<td>전체 탐색</td>
<td>O(N + M) (N: 노드 수, M: 간선 수)</td>
</tr>
</tbody></table>
<hr>
<h3 id="실전-문제-유형">실전 문제 유형</h3>
<table>
<thead>
<tr>
<th>문제 유형</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>섬의 개수</td>
<td>DFS로 연결된 영역 탐색</td>
</tr>
<tr>
<td>조합, 순열</td>
<td>DFS + visited 배열로 구현</td>
</tr>
<tr>
<td>미로 경로 찾기</td>
<td>한 갈래씩 끝까지 가며 경로 탐색</td>
</tr>
<tr>
<td>백트래킹</td>
<td>조건 분기 + 되돌아가기</td>
</tr>
<tr>
<td>사이클 탐지</td>
<td>방문 중인 노드가 또 나오면 순환 존재</td>
</tr>
</tbody></table>
<hr>
<h3 id="python-vs-c-구현-차이">Python vs C 구현 차이</h3>
<table>
<thead>
<tr>
<th>항목</th>
<th>Python</th>
<th>C</th>
</tr>
</thead>
<tbody><tr>
<td>재귀</td>
<td>자유롭게 사용</td>
<td>스택 오버플로우 주의</td>
</tr>
<tr>
<td>스택</td>
<td>리스트로 사용 가능</td>
<td>배열 + top 포인터 직접 구현</td>
</tr>
<tr>
<td>인접 리스트</td>
<td>리스트 배열</td>
<td>포인터 배열 또는 연결 리스트</td>
</tr>
<tr>
<td>visited 배열</td>
<td>bool 리스트</td>
<td>bool visited[] 선언</td>
</tr>
</tbody></table>
<hr>
<h3 id="연관-개념">연관 개념</h3>
<table>
<thead>
<tr>
<th>개념</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>Stack</td>
<td>DFS 내부 동작의 원리</td>
</tr>
<tr>
<td>백트래킹</td>
<td>DFS 기반 조합/경로 탐색 알고리즘</td>
</tr>
<tr>
<td>visited 배열</td>
<td>중복 방문 방지 필수</td>
</tr>
<tr>
<td>순열/조합 생성</td>
<td>DFS + 조건 분기로 구현</td>
</tr>
</tbody></table>
<hr>
<h3 id="핵심-요약">핵심 요약</h3>
<ul>
<li>DFS는 <strong>깊이 우선 탐색</strong>으로, 한 갈래 끝까지 내려간 후 되돌아옴</li>
<li>BFS와는 반대로 <strong>경로 탐색, 완전탐색, 백트래킹 문제에 적합</strong></li>
<li>재귀 방식이 가장 간단하지만, 깊이가 깊으면 스택 방식 필요</li>
<li><strong>방문 여부 체크는 필수</strong></li>
<li>실전에서는 <strong>섬의 개수, 미로 찾기, 백트래킹</strong> 유형에서 빈출</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[BFS (Breadth-First Search)]]></title>
            <link>https://velog.io/@jh_y/BFS-Breadth-First-Search</link>
            <guid>https://velog.io/@jh_y/BFS-Breadth-First-Search</guid>
            <pubDate>Sun, 30 Mar 2025 07:13:58 GMT</pubDate>
            <description><![CDATA[<h3 id="bfs란">BFS란?</h3>
<ul>
<li><strong>너비 우선 탐색</strong>: 가까운 정점부터 넓게 탐색</li>
<li><strong>Queue(큐)</strong> 자료구조를 사용해 구현</li>
<li>시작점에서 인접한 정점을 먼저 탐색 후, 더 깊은 곳으로 진행</li>
</ul>
<hr>
<h3 id="사용-목적">사용 목적</h3>
<table>
<thead>
<tr>
<th>목적</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>최단 거리 탐색</td>
<td>가중치 없는 그래프에서 가장 짧은 거리 보장</td>
</tr>
<tr>
<td>단계별 탐색</td>
<td>거리 개념이 있는 문제</td>
</tr>
<tr>
<td>연결 요소 확인</td>
<td>연결된 구성 요소를 모두 찾을 때</td>
</tr>
<tr>
<td>실시간 확산 구조</td>
<td>전파, 감염, 퍼짐 등 문제 유형에 적합</td>
</tr>
</tbody></table>
<hr>
<h3 id="동작-순서">동작 순서</h3>
<ol>
<li>시작 노드를 큐에 넣고 방문 처리</li>
<li>큐에서 노드를 꺼냄</li>
<li>인접 노드를 모두 큐에 추가</li>
<li>큐가 빌 때까지 반복</li>
</ol>
<hr>
<h3 id="구현-예시-python">구현 예시 (Python)</h3>
<pre><code class="language-python">from collections import deque

def bfs(graph, start, visited):
    queue = deque([start])
    visited[start] = True

    while queue:
        v = queue.popleft()
        print(v, end=&#39; &#39;)
        for neighbor in graph[v]:
            if not visited[neighbor]:
                queue.append(neighbor)
                visited[neighbor] = True
</code></pre>
<pre><code class="language-python"># 호출 예시
graph = [
    [],         # 0번 노드 미사용
    [2, 3],     # 1 → 2, 3
    [1, 4],
    [1, 4],
    [2, 3]
]
visited = [False] * 5
bfs(graph, 1, visited)  # 출력: 1 2 3 4
</code></pre>
<hr>
<h3 id="시간-복잡도">시간 복잡도</h3>
<blockquote>
<ul>
<li>O(N + M)
  (N: 노드 수, M: 간선 수)</li>
</ul>
</blockquote>
<hr>
<h3 id="실전-예시-문제">실전 예시 문제</h3>
<table>
<thead>
<tr>
<th>유형</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>미로 탐색</td>
<td>최단 거리 찾기</td>
</tr>
<tr>
<td>전염 시뮬레이션</td>
<td>바이러스 전파, 물 확산 등</td>
</tr>
<tr>
<td>거리 계산</td>
<td>특정 노드에서 모든 노드까지 거리</td>
</tr>
<tr>
<td>연결 요소</td>
<td>연결된 덩어리 개수 파악</td>
</tr>
</tbody></table>
<hr>
<h3 id="핵심-요약">핵심 요약</h3>
<ul>
<li>BFS는 <strong>가까운 노드부터 탐색</strong></li>
<li><strong>Queue</strong> 사용 + 방문 체크 필수</li>
<li><strong>가중치 없는 최단 거리</strong> 문제에서 가장 많이 사용됨</li>
<li>Python은 <code>deque</code>, C는 배열 기반 큐 직접 구현</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[그래프 (Graph)]]></title>
            <link>https://velog.io/@jh_y/%EA%B7%B8%EB%9E%98%ED%94%84-Graph</link>
            <guid>https://velog.io/@jh_y/%EA%B7%B8%EB%9E%98%ED%94%84-Graph</guid>
            <pubDate>Sun, 30 Mar 2025 07:06:48 GMT</pubDate>
            <description><![CDATA[<h3 id="그래프란">그래프란?</h3>
<ul>
<li><em>정점(Vertex)*</em>과 <strong>간선(Edge)</strong>으로 구성된 자료구조</li>
<li>정점 간의 <strong>연결 관계(네트워크)</strong>를 표현</li>
<li>방향, 가중치, 연결성에 따라 다양한 그래프 형태 존재</li>
</ul>
<hr>
<h3 id="핵심-용어">핵심 용어</h3>
<table>
<thead>
<tr>
<th>용어</th>
<th>의미</th>
</tr>
</thead>
<tbody><tr>
<td>Vertex (정점, 노드)</td>
<td>데이터를 나타내는 단위</td>
</tr>
<tr>
<td>Edge (간선, 아크)</td>
<td>정점 간의 연결</td>
</tr>
<tr>
<td>Directed</td>
<td>방향이 있는 간선 (A → B)</td>
</tr>
<tr>
<td>Undirected</td>
<td>방향이 없는 간선 (A — B)</td>
</tr>
<tr>
<td>Weight</td>
<td>간선에 부여된 비용/거리</td>
</tr>
<tr>
<td>Degree</td>
<td>정점에 연결된 간선 수 (진입차수 / 진출차수)</td>
</tr>
</tbody></table>
<hr>
<h3 id="그래프의-종류">그래프의 종류</h3>
<table>
<thead>
<tr>
<th>분류 기준</th>
<th>종류</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>방향성</td>
<td>방향 그래프 / 무방향 그래프</td>
<td>간선의 방향 유무</td>
</tr>
<tr>
<td>가중치</td>
<td>가중치 그래프 / 무가중치 그래프</td>
<td>간선에 값 부여 여부</td>
</tr>
<tr>
<td>연결 여부</td>
<td>연결 / 비연결</td>
<td>모든 노드가 연결되어 있는지</td>
</tr>
<tr>
<td>순환 여부</td>
<td>순환 그래프 / 비순환 그래프</td>
<td>사이클 존재 여부</td>
</tr>
<tr>
<td>특수 구조</td>
<td>트리, DAG</td>
<td>트리 = 비순환 연결 그래프, DAG = 방향 + 비순환</td>
</tr>
</tbody></table>
<hr>
<h3 id="그래프-구현-방법-python-기준">그래프 구현 방법 (Python 기준)</h3>
<h4 id="인접-행렬-adjacency-matrix">인접 행렬 (Adjacency Matrix)</h4>
<pre><code class="language-python">n = 4
graph = [[0]*n for _ in range(n)]
graph[0][1] = 1  # 0 → 1 간선 추가
</code></pre>
<ul>
<li>메모리: O(N²)</li>
<li>모든 간선 확인 빠름</li>
<li><strong>간선이 적을 땐 비효율적</strong></li>
</ul>
<hr>
<h4 id="인접-리스트-adjacency-list">인접 리스트 (Adjacency List)</h4>
<pre><code class="language-python">graph = [[] for _ in range(4)]
graph[0].append(1)  # 0 → 1 간선 추가
</code></pre>
<ul>
<li>메모리: O(N + M)</li>
<li>연결된 노드만 탐색 가능</li>
<li><strong>일반적으로 선호되는 방식</strong></li>
</ul>
<hr>
<h4 id="딕셔너리-기반">딕셔너리 기반</h4>
<pre><code class="language-python">graph = {
    &#39;A&#39;: [&#39;B&#39;, &#39;C&#39;],
    &#39;B&#39;: [&#39;D&#39;],
    &#39;C&#39;: [],
    &#39;D&#39;: []
}
</code></pre>
<ul>
<li>문자열 정점 등 다양한 데이터 처리 시 유용</li>
</ul>
<hr>
<h3 id="시간-복잡도-비교">시간 복잡도 비교</h3>
<table>
<thead>
<tr>
<th>구현 방식</th>
<th>메모리</th>
<th>탐색 속도</th>
</tr>
</thead>
<tbody><tr>
<td>인접 행렬</td>
<td>O(N²)</td>
<td>모든 정점 간 간선 확인 O(1)</td>
</tr>
<tr>
<td>인접 리스트</td>
<td>O(N + M)</td>
<td>연결된 노드만 탐색 O(연결 수)</td>
</tr>
</tbody></table>
<hr>
<h3 id="실전-알고리즘-예시">실전 알고리즘 예시</h3>
<table>
<thead>
<tr>
<th>알고리즘</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>DFS / BFS</td>
<td>정점 방문 순회</td>
</tr>
<tr>
<td>다익스트라</td>
<td>가중치 있는 최단 경로</td>
</tr>
<tr>
<td>위상 정렬</td>
<td>방향 그래프 + 진입 차수</td>
</tr>
<tr>
<td>연결 요소</td>
<td>비연결 그래프의 개수 파악</td>
</tr>
<tr>
<td>사이클 탐지</td>
<td>DFS + 방문 체크</td>
</tr>
</tbody></table>
<hr>
<h3 id="python-vs-c-구현-차이">Python vs C 구현 차이</h3>
<table>
<thead>
<tr>
<th>항목</th>
<th>Python</th>
<th>C</th>
</tr>
</thead>
<tbody><tr>
<td>리스트</td>
<td>리스트, 딕셔너리</td>
<td>배열, 포인터 배열</td>
</tr>
<tr>
<td>동적 메모리</td>
<td>자동 관리</td>
<td>malloc, free 필요</td>
</tr>
<tr>
<td>DFS/BFS</td>
<td>스택, 큐 모듈 활용</td>
<td>직접 큐/스택 구현 필요</td>
</tr>
<tr>
<td>문자열 처리</td>
<td>편리한 인덱싱</td>
<td>포인터, 문자열 비교 직접 구현</td>
</tr>
</tbody></table>
<hr>
<h3 id="자주-나오는-개념-정리">자주 나오는 개념 정리</h3>
<table>
<thead>
<tr>
<th>개념</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>인접(adjacent)</td>
<td>직접 연결된 노드</td>
</tr>
<tr>
<td>연결 요소</td>
<td>그래프 내 끊어진 연결 블록 수</td>
</tr>
<tr>
<td>진입 차수 / 진출 차수</td>
<td>들어오는 간선 / 나가는 간선 수</td>
</tr>
<tr>
<td>경로(Path)</td>
<td>정점들의 연결된 순서</td>
</tr>
<tr>
<td>사이클(Cycle)</td>
<td>출발점과 도착점이 같은 경로 존재 여부</td>
</tr>
</tbody></table>
<hr>
<h3 id="핵심-요약">핵심 요약</h3>
<ul>
<li>그래프는 <strong>정점(Vertex) + 간선(Edge)</strong>로 구성</li>
<li>구현은 대부분 <strong>인접 리스트</strong> 사용</li>
<li>문제 조건에 따라 방향성/가중치/연결성 확인 필수</li>
<li>실전 문제는 <strong>그래프 탐색 + 자료구조 구현 능력</strong>이 핵심</li>
<li>DFS, BFS, 다익스트라, 위상정렬 등 <strong>그래프 알고리즘</strong>과 연결됨</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[week2 마무리]]></title>
            <link>https://velog.io/@jh_y/week2-%EB%A7%88%EB%AC%B4%EB%A6%AC</link>
            <guid>https://velog.io/@jh_y/week2-%EB%A7%88%EB%AC%B4%EB%A6%AC</guid>
            <pubDate>Sun, 30 Mar 2025 06:58:28 GMT</pubDate>
            <description><![CDATA[<h3 id="이분-탐색-binary-search">이분 탐색 (Binary Search)</h3>
<ul>
<li><strong>정렬된 배열</strong>에서 탐색 구간을 절반씩 줄이며 값을 찾는 알고리즘</li>
<li><em>O(log N)*</em>의 빠른 탐색 성능</li>
<li>조건을 만족하는 <strong>최소/최댓값을 찾는 문제</strong>에도 자주 사용됨</li>
</ul>
<h4 id="전제-조건">전제 조건</h4>
<ul>
<li>입력 배열은 반드시 오름차순 정렬되어 있어야 함</li>
</ul>
<h4 id="주요-활용">주요 활용</h4>
<ul>
<li>값 존재 여부 확인</li>
<li>파라메트릭 서치</li>
<li>lower_bound, upper_bound 구현</li>
</ul>
<h4 id="구현-방식">구현 방식</h4>
<ul>
<li>반복문, 재귀 함수</li>
<li>파이썬 내장: <code>bisect</code> (단 실전에서는 직접 구현 연습 필수)</li>
</ul>
<hr>
<h3 id="분할-정복-divide-and-conquer">분할 정복 (Divide and Conquer)</h3>
<ul>
<li><strong>큰 문제를 작게 나누고(분할) → 해결(정복) → 결과를 합침</strong></li>
<li>재귀 기반 알고리즘 설계의 핵심 패턴</li>
</ul>
<h4 id="대표-알고리즘">대표 알고리즘</h4>
<ul>
<li>병합 정렬 (Merge Sort)</li>
<li>거듭제곱 계산 (aⁿ)</li>
<li>최대 구간합 문제</li>
</ul>
<h4 id="시간-복잡도">시간 복잡도</h4>
<ul>
<li>O(log N) 또는 O(N log N)</li>
</ul>
<h4 id="특징">특징</h4>
<ul>
<li>문제를 나눌 수 있어야 하며, 나눈 결과를 다시 합쳐서 정답을 만들어야 함</li>
</ul>
<hr>
<h3 id="스택-stack">스택 (Stack)</h3>
<ul>
<li><strong>LIFO 구조</strong>: 나중에 들어온 데이터가 먼저 나감</li>
<li><strong>시간 복잡도: O(1)</strong> (삽입, 삭제)</li>
</ul>
<h4 id="기본-연산">기본 연산</h4>
<ul>
<li><code>push()</code>, <code>pop()</code>, <code>peek()</code>, <code>is_empty()</code></li>
</ul>
<h4 id="주요-활용-1">주요 활용</h4>
<ul>
<li>괄호 유효성 검사</li>
<li>수식 후위 표기법 계산</li>
<li>오큰수, 탑 문제 등</li>
</ul>
<h4 id="파이썬-구현">파이썬 구현</h4>
<ul>
<li>리스트 <code>append()</code>, <code>pop()</code></li>
</ul>
<hr>
<h3 id="큐-queue">큐 (Queue)</h3>
<ul>
<li><strong>FIFO 구조</strong>: 먼저 들어온 데이터가 먼저 나감</li>
<li><strong>시간 복잡도: O(1)</strong> (deque 기준)</li>
</ul>
<h4 id="기본-연산-1">기본 연산</h4>
<ul>
<li><code>enqueue()</code>, <code>dequeue()</code>, <code>peek()</code>, <code>is_empty()</code></li>
</ul>
<h4 id="주요-활용-2">주요 활용</h4>
<ul>
<li>BFS 탐색</li>
<li>프린터 대기열</li>
<li>생산자-소비자 구조, 캐시 시스템</li>
</ul>
<h4 id="파이썬-구현-1">파이썬 구현</h4>
<ul>
<li><code>collections.deque</code> 사용</li>
<li><code>append()</code>, <code>popleft()</code></li>
</ul>
<hr>
<h3 id="우선순위-큐-priority-queue">우선순위 큐 (Priority Queue)</h3>
<ul>
<li>값의 크기(우선순위)에 따라 먼저 꺼내는 큐</li>
<li>일반 큐와 달리 <strong>최소값 또는 최대값을 빠르게 꺼낼 수 있음</strong></li>
<li><strong>Heap 자료구조</strong>로 구현됨</li>
</ul>
<h4 id="시간-복잡도-1">시간 복잡도</h4>
<ul>
<li>삽입 / 삭제: O(log N)</li>
</ul>
<h4 id="파이썬-구현-2">파이썬 구현</h4>
<ul>
<li><code>heapq</code> 모듈 사용 (<code>heappush()</code>, <code>heappop()</code>)</li>
</ul>
<h4 id="주요-활용-3">주요 활용</h4>
<ul>
<li>다익스트라 알고리즘</li>
<li>K번째 큰 수</li>
<li>스케줄링, 대기열 처리 문제</li>
</ul>
<hr>
<h3 id="연결-리스트-linked-list">연결 리스트 (Linked List)</h3>
<ul>
<li>각 노드가 다음 노드를 가리키는 <strong>포인터 기반의 선형 자료구조</strong></li>
<li><strong>중간 삽입/삭제가 O(1)</strong> 로 매우 빠름 (단 탐색은 O(N))</li>
</ul>
<h4 id="종류">종류</h4>
<ul>
<li>단일 연결 리스트 (singly)</li>
<li>이중 연결 리스트 (doubly)</li>
</ul>
<h4 id="주요-활용-4">주요 활용</h4>
<ul>
<li>LRU 캐시</li>
<li>내부적으로 큐, 스택 구현 시 활용</li>
<li>노드 삭제/삽입, 역순 연결 등</li>
</ul>
<h4 id="파이썬-구현-3">파이썬 구현</h4>
<ul>
<li><code>Node</code> 클래스 + <code>LinkedList</code> 클래스 구성</li>
</ul>
<hr>
<h3 id="해시-테이블-hash-table">해시 테이블 (Hash Table)</h3>
<ul>
<li>Key → Hash Function → Index → Value 저장</li>
<li><strong>탐색/삽입/삭제 평균 O(1)</strong></li>
</ul>
<h4 id="주요-특징">주요 특징</h4>
<ul>
<li>Key는 immutable 타입이어야 함</li>
<li>충돌이 발생할 수 있으므로 충돌 처리 필요 (chaining, open addressing 등)</li>
</ul>
<h4 id="파이썬-구현-4">파이썬 구현</h4>
<ul>
<li><code>dict</code>, <code>defaultdict</code>, <code>get()</code>, <code>in</code></li>
</ul>
<h4 id="주요-활용-5">주요 활용</h4>
<ul>
<li>등장 횟수 세기</li>
<li>중복 체크</li>
<li>빠른 조회, 맵핑</li>
</ul>
<hr>
<h2 id="week2-실전-대비-핵심-요약">Week2 실전 대비 핵심 요약</h2>
<table>
<thead>
<tr>
<th>주제</th>
<th>평균 시간 복잡도</th>
<th>주요 활용</th>
</tr>
</thead>
<tbody><tr>
<td>이분 탐색</td>
<td>O(log N)</td>
<td>정렬 배열 탐색, 조건 만족 최소값</td>
</tr>
<tr>
<td>분할 정복</td>
<td>문제마다 다름</td>
<td>정렬, 제곱, 영역 분할</td>
</tr>
<tr>
<td>스택</td>
<td>O(1)</td>
<td>괄호검사, 수식변환, 오큰수</td>
</tr>
<tr>
<td>큐</td>
<td>O(1)</td>
<td>BFS, 대기열 처리</td>
</tr>
<tr>
<td>우선순위 큐</td>
<td>O(log N)</td>
<td>최단경로, 실시간 정렬</td>
</tr>
<tr>
<td>연결 리스트</td>
<td>삽입/삭제 O(1), 탐색 O(N)</td>
<td>캐시, 중간 삽입</td>
</tr>
<tr>
<td>해시 테이블</td>
<td>평균 O(1)</td>
<td>등장 횟수, 키-값 매핑</td>
</tr>
</tbody></table>
<hr>
<h3 id="복습-가이드">복습 가이드</h3>
<ul>
<li>각 구조/알고리즘의 <strong>시간복잡도, 활용 사례, 구현 방식</strong>을 중심으로 다시 정리</li>
<li>파이썬 기본 모듈(<code>collections</code>, <code>heapq</code>, <code>bisect</code>) 활용법 연습</li>
<li>C로 전환할 경우 직접 구현 방식도 병행 학습</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[해시 테이블 (Hash Table)]]></title>
            <link>https://velog.io/@jh_y/%ED%95%B4%EC%8B%9C-%ED%85%8C%EC%9D%B4%EB%B8%94-Hash-Table</link>
            <guid>https://velog.io/@jh_y/%ED%95%B4%EC%8B%9C-%ED%85%8C%EC%9D%B4%EB%B8%94-Hash-Table</guid>
            <pubDate>Sun, 30 Mar 2025 06:54:23 GMT</pubDate>
            <description><![CDATA[<h3 id="해시-테이블이란">해시 테이블이란?</h3>
<ul>
<li>Key를 해시 함수에 넣어 <strong>고유한 인덱스</strong>를 생성하고, 그 인덱스에 데이터를 저장하는 구조</li>
<li><strong>Key-Value 쌍</strong>으로 데이터를 저장</li>
<li>빠른 탐색, 삽입, 삭제 가능</li>
<li><strong>파이썬에서는 <code>dict</code></strong>, <strong>C에서는 배열 + 해시 함수 직접 구현</strong></li>
</ul>
<hr>
<h3 id="주요-특징">주요 특징</h3>
<ul>
<li>평균 시간 복잡도는 O(1)</li>
<li>Key 값은 변경 불가능한 자료형만 사용 가능 (str, int, tuple 등)</li>
<li>해시 충돌이 발생할 수 있으며 이를 처리하는 로직이 필요함</li>
</ul>
<hr>
<h3 id="언제-사용되는가">언제 사용되는가?</h3>
<table>
<thead>
<tr>
<th>상황</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>빠른 탐색이 필요할 때</td>
<td>배열보다 훨씬 빠르게 값 조회 가능</td>
</tr>
<tr>
<td>키 기반 매핑이 필요할 때</td>
<td>사용자 ID → 정보, 상품명 → 가격 등</td>
</tr>
<tr>
<td>중복 체크</td>
<td>등장 여부 확인, 카운팅</td>
</tr>
<tr>
<td>실전 문제 대부분</td>
<td>문자열, 배열 문제에 자주 등장</td>
</tr>
</tbody></table>
<hr>
<h3 id="자료구조-동작-방식">자료구조 동작 방식</h3>
<ol>
<li>Key에 해시 함수를 적용하여 index 계산</li>
<li>해당 index에 Value 저장</li>
<li>같은 index가 겹치면 충돌 발생 → 별도 충돌 처리 필요</li>
</ol>
<hr>
<h3 id="해시-테이블-구현-예제">해시 테이블 구현 예제</h3>
<h4 id="기본-사용">기본 사용</h4>
<pre><code class="language-python">my_dict = {}
my_dict[&#39;apple&#39;] = 3
print(my_dict[&#39;apple&#39;])   # 3
my_dict[&#39;apple&#39;] = 5       # 값 수정
del my_dict[&#39;apple&#39;]       # 값 삭제
</code></pre>
<h4 id="존재-여부-확인">존재 여부 확인</h4>
<pre><code class="language-python">if &#39;banana&#39; in my_dict:
    print(&quot;존재함&quot;)
</code></pre>
<h4 id="문자-빈도수-세기">문자 빈도수 세기</h4>
<pre><code class="language-python">s = &quot;banana&quot;
count = {}
for c in s:
    count[c] = count.get(c, 0) + 1

# 결과: {&#39;b&#39;: 1, &#39;a&#39;: 3, &#39;n&#39;: 2}
</code></pre>
<hr>
<h3 id="시간-복잡도">시간 복잡도</h3>
<table>
<thead>
<tr>
<th>연산</th>
<th>평균</th>
<th>최악 (충돌 심할 때)</th>
</tr>
</thead>
<tbody><tr>
<td>삽입</td>
<td>O(1)</td>
<td>O(N)</td>
</tr>
<tr>
<td>탐색</td>
<td>O(1)</td>
<td>O(N)</td>
</tr>
<tr>
<td>삭제</td>
<td>O(1)</td>
<td>O(N)</td>
</tr>
</tbody></table>
<p>※ 일반적으로 충돌은 잘 발생하지 않도록 구현</p>
<hr>
<h3 id="실전-문제-유형-예시">실전 문제 유형 예시</h3>
<table>
<thead>
<tr>
<th>문제 유형</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>등장 횟수 세기</td>
<td>문자열, 숫자 빈도수 계산</td>
</tr>
<tr>
<td>중복 체크</td>
<td>이미 등장한 값 빠르게 확인</td>
</tr>
<tr>
<td>두 수의 합</td>
<td>값과 차이를 저장 후 바로 비교</td>
</tr>
<tr>
<td>애너그램 판별</td>
<td>두 문자열의 문자 빈도 비교</td>
</tr>
<tr>
<td>스트링 매핑 문제</td>
<td>문자열 → 정수 변환, 좌표 압축 등</td>
</tr>
</tbody></table>
<hr>
<h3 id="c언어-구현-시-고려사항">C언어 구현 시 고려사항</h3>
<table>
<thead>
<tr>
<th>항목</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>해시 함수</td>
<td>직접 설계 필요 (<code>djb2</code>, <code>BKDR</code>, mod 기반 등)</td>
</tr>
<tr>
<td>충돌 처리</td>
<td>체이닝(연결 리스트) 또는 오픈 주소 방식</td>
</tr>
<tr>
<td>Key 관리</td>
<td>구조체 + 포인터 조합으로 직접 구현</td>
</tr>
<tr>
<td>문자열 비교</td>
<td>strcmp 등 문자열 비교 함수 필요</td>
</tr>
<tr>
<td>메모리 해제</td>
<td>사용 후 free 처리 필수</td>
</tr>
</tbody></table>
<hr>
<h3 id="관련-파이썬-함수">관련 파이썬 함수</h3>
<table>
<thead>
<tr>
<th>함수</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>dict()</code></td>
<td>딕셔너리 생성</td>
</tr>
<tr>
<td><code>in</code></td>
<td>키 존재 여부 확인</td>
</tr>
<tr>
<td><code>get(key, default)</code></td>
<td>키가 없을 경우 기본값 반환</td>
</tr>
<tr>
<td><code>keys()</code> / <code>values()</code></td>
<td>키 / 값 목록 조회</td>
</tr>
<tr>
<td><code>collections.defaultdict</code></td>
<td>기본값을 갖는 딕셔너리 생성</td>
</tr>
</tbody></table>
<hr>
<h3 id="핵심-요약">핵심 요약</h3>
<ul>
<li>해시 테이블은 <strong>O(1)</strong> 성능의 탐색/저장 구조로, 알고리즘에서 거의 필수</li>
<li>파이썬은 <code>dict</code>로 매우 간단하게 사용 가능</li>
<li>실전에서는 빈도수 세기, 중복 확인, 매핑 등에서 자주 등장</li>
<li>C에서는 해시 함수, 충돌 처리, 메모리 관리까지 전부 직접 구현해야 함</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>