<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://mellow1213.github.io//feed.xml" rel="self" type="application/atom+xml" /><link href="https://mellow1213.github.io//" rel="alternate" type="text/html" /><updated>2024-11-04T07:00:58+00:00</updated><id>https://mellow1213.github.io//feed.xml</id><title type="html">Shining-Archive</title><subtitle>게임 개발자의 지식 창고</subtitle><author><name>Mellow1213</name></author><entry><title type="html">[BOJ][Silver I] 7562번: 나이트의 이동</title><link href="https://mellow1213.github.io//boj/codding-test-02/" rel="alternate" type="text/html" title="[BOJ][Silver I] 7562번: 나이트의 이동" /><published>2024-11-04T00:00:00+00:00</published><updated>2024-11-04T00:00:00+00:00</updated><id>https://mellow1213.github.io//boj/codding-test-02</id><content type="html" xml:base="https://mellow1213.github.io//boj/codding-test-02/"><![CDATA[<h1 id="문제">문제</h1>
<hr />

<p><a href="https://www.acmicpc.net/problem/7562">7562번: 나이트의 이동 바로가기</a></p>

<p><img src="/images/image.png" alt="alt text" />)</p>

<p>나이트가 이동하려고 하는 좌표가 있으면 몇 번 움직여야 해당 좌표로 움직이나? 에 대한 문제.</p>

<p>체스 말 나이트의 이동 방식을 기반으로 특정 위치까지 도달하는데 걸리는 이동 시간의 최소를 구하는 문제이다.</p>

<p>즉 좌표 상에서 최소 거리를 구하는 BFS 문제이다.
대신 X, Y가 +1 -1씩 움직이는 것이 아니라 나이트의 이동처럼 대각선 위와 같은 방식으로 탐색을 하면 된다.</p>

<p>테스트케이스는 따로 빼고,
처음 시작하는 좌표와 도착 좌표를 받은 후
BFS로 탐색을 진행한다.</p>

<p>좌표 기반 BFS므로 범위 설정 잘 해주면 한 좌표에서 다른 좌표로 나이트가 갈 수 있는 좌표의 범위가 8경우가 됨<br />
방문 여부를 고려해서 해당 범위마다 탐색해주자.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;queue&gt;</span><span class="cp">
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>

<span class="k">const</span> <span class="kt">int</span> <span class="n">dx</span><span class="p">[</span><span class="mi">8</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">};</span>
<span class="k">const</span> <span class="kt">int</span> <span class="n">dy</span><span class="p">[</span><span class="mi">8</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">};</span>
<span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">vec</span><span class="p">;</span>

<span class="kt">bool</span> <span class="n">OutOfBound</span><span class="p">(</span><span class="k">const</span> <span class="kt">int</span><span class="o">&amp;</span> <span class="n">x</span><span class="p">,</span> <span class="k">const</span> <span class="kt">int</span><span class="o">&amp;</span> <span class="n">y</span><span class="p">){</span>
    <span class="k">return</span> <span class="n">x</span><span class="o">&lt;</span><span class="mi">0</span> <span class="o">||</span> <span class="n">x</span><span class="o">&gt;=</span><span class="n">vec</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">||</span> <span class="n">y</span><span class="o">&lt;</span><span class="mi">0</span> <span class="o">||</span> <span class="n">y</span><span class="o">&gt;=</span><span class="n">vec</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="n">BFS</span><span class="p">(</span><span class="kt">int</span><span class="o">&amp;</span> <span class="n">startX</span><span class="p">,</span> <span class="kt">int</span><span class="o">&amp;</span> <span class="n">startY</span><span class="p">,</span> <span class="kt">int</span><span class="o">&amp;</span> <span class="n">endX</span><span class="p">,</span> <span class="kt">int</span><span class="o">&amp;</span> <span class="n">endY</span><span class="p">){</span>
    <span class="n">queue</span><span class="o">&lt;</span><span class="n">pair</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">q</span><span class="p">;</span>
    <span class="n">q</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">make_pair</span><span class="p">(</span><span class="n">startX</span><span class="p">,</span> <span class="n">startY</span><span class="p">));</span>
    <span class="n">vec</span><span class="p">[</span><span class="n">startX</span><span class="p">][</span><span class="n">startY</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    
    <span class="k">while</span><span class="p">(</span><span class="o">!</span><span class="n">q</span><span class="p">.</span><span class="n">empty</span><span class="p">()){</span>
        <span class="kt">int</span> <span class="n">x</span> <span class="o">=</span> <span class="n">q</span><span class="p">.</span><span class="n">front</span><span class="p">().</span><span class="n">first</span><span class="p">;</span>
        <span class="kt">int</span> <span class="n">y</span> <span class="o">=</span> <span class="n">q</span><span class="p">.</span><span class="n">front</span><span class="p">().</span><span class="n">second</span><span class="p">;</span>
        <span class="k">if</span><span class="p">(</span><span class="n">x</span><span class="o">==</span><span class="n">endX</span> <span class="o">&amp;&amp;</span> <span class="n">y</span><span class="o">==</span><span class="n">endY</span><span class="p">){</span>
            <span class="k">break</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="n">q</span><span class="p">.</span><span class="n">pop</span><span class="p">();</span>
        
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o">&lt;</span><span class="mi">8</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
            <span class="kt">int</span> <span class="n">curX</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">dx</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
            <span class="kt">int</span> <span class="n">curY</span> <span class="o">=</span> <span class="n">y</span> <span class="o">+</span> <span class="n">dy</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
            
            <span class="k">if</span><span class="p">(</span><span class="n">OutOfBound</span><span class="p">(</span><span class="n">curX</span><span class="p">,</span> <span class="n">curY</span><span class="p">))</span>
                <span class="k">continue</span><span class="p">;</span>
                
            <span class="k">if</span><span class="p">(</span><span class="n">vec</span><span class="p">[</span><span class="n">curX</span><span class="p">][</span><span class="n">curY</span><span class="p">]</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">){</span>
                <span class="n">vec</span><span class="p">[</span><span class="n">curX</span><span class="p">][</span><span class="n">curY</span><span class="p">]</span> <span class="o">=</span> <span class="n">vec</span><span class="p">[</span><span class="n">x</span><span class="p">][</span><span class="n">y</span><span class="p">]</span><span class="o">+</span><span class="mi">1</span><span class="p">;</span>
                <span class="n">q</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">make_pair</span><span class="p">(</span><span class="n">curX</span><span class="p">,</span> <span class="n">curY</span><span class="p">));</span>
            <span class="p">}</span>
        <span class="p">}</span>
    <span class="p">}</span>    
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">vec</span><span class="p">[</span><span class="n">endX</span><span class="p">][</span><span class="n">endY</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="n">Solve</span><span class="p">(){</span>
    <span class="kt">int</span> <span class="n">length</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">startX</span><span class="p">,</span> <span class="n">startY</span><span class="p">,</span> <span class="n">destX</span><span class="p">,</span> <span class="n">destY</span><span class="p">;</span>
    <span class="n">cin</span> <span class="o">&gt;&gt;</span> <span class="n">length</span><span class="p">;</span>
    <span class="n">cin</span> <span class="o">&gt;&gt;</span> <span class="n">startX</span> <span class="o">&gt;&gt;</span> <span class="n">startY</span><span class="p">;</span>
    <span class="n">cin</span> <span class="o">&gt;&gt;</span> <span class="n">destX</span> <span class="o">&gt;&gt;</span> <span class="n">destY</span><span class="p">;</span>
    
    <span class="n">vec</span><span class="p">.</span><span class="n">assign</span><span class="p">(</span><span class="n">length</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">length</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">));</span>
    
    <span class="n">BFS</span><span class="p">(</span><span class="n">startX</span><span class="p">,</span> <span class="n">startY</span><span class="p">,</span> <span class="n">destX</span><span class="p">,</span> <span class="n">destY</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="n">main</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">ios_base</span><span class="o">::</span><span class="n">sync_with_stdio</span><span class="p">(</span><span class="nb">false</span><span class="p">);</span>
    <span class="n">cin</span><span class="p">.</span><span class="n">tie</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="n">cout</span><span class="p">.</span><span class="n">tie</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
    <span class="kt">int</span> <span class="n">testCase</span><span class="p">;</span>
    <span class="n">cin</span> <span class="o">&gt;&gt;</span> <span class="n">testCase</span><span class="p">;</span>
    
    <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o">&lt;</span><span class="n">testCase</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
        <span class="n">Solve</span><span class="p">();</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>]]></content><author><name>Mellow1213</name></author><category term="boj" /><summary type="html"><![CDATA[좌표 기반 BFS 응용]]></summary></entry><entry><title type="html">[BOJ][Silver II] 15663번: A -&amp;gt; B</title><link href="https://mellow1213.github.io//boj/codding-test-01/" rel="alternate" type="text/html" title="[BOJ][Silver II] 15663번: A -&amp;gt; B" /><published>2024-10-14T00:00:00+00:00</published><updated>2024-10-14T00:00:00+00:00</updated><id>https://mellow1213.github.io//boj/codding-test-01</id><content type="html" xml:base="https://mellow1213.github.io//boj/codding-test-01/"><![CDATA[<h1 id="문제">문제</h1>
<hr />

<p><a href="https://www.acmicpc.net/problem/16953">No. 15663 A -&gt; B 문제 바로가기</a></p>
<h1 id="접근-방법">접근 방법</h1>
<hr />

<p>두 개의 연산이 정의됨.</p>
<ul>
  <li>2를 곱하기 ( *2 )</li>
  <li>1을 수의 가장 오른 쪽에 추가 (*10+1)</li>
</ul>

<p>이 두 개의 연산으로 A를 B로 만드는데 드는 최소 연산 값을 찾으면 된다.</p>

<p>그러면 A에다가 1을 몇 번 추가하고, 2를 몇 번 곱하면 B가 나온다는 얘기인데, A-&gt;B의 과정에서는 언제 1을 더하고 2를 곱해야 하는지 확실하지 않을 때가 많다.</p>

<p>그러면 이렇게 생각해보자.
A에서 B를 가는 과정은 불확실하다. 그러나 A-&gt;B의 과정이 된다고 가정하면, 두 연산만으로 A가 B에 도달하는 한 가지의 경우의 수만 있다. 따라서 A-&gt;B도, B-&gt;A도 경우의 수가 딱 하나 존재하고 거꾸로 B에서 A로 가는 조건을 하나하나 해주면 A가 나올 것이다.</p>

<table>
  <thead>
    <tr>
      <th style="text-align: center">기준</th>
      <th style="text-align: center">A의 관점</th>
      <th style="text-align: center">B의 관점</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: center">연산 1</td>
      <td style="text-align: center">A * 2</td>
      <td style="text-align: center">B / 2</td>
    </tr>
    <tr>
      <td style="text-align: center">연산 2</td>
      <td style="text-align: center">A * 10 + 1 (1을 수의 오른 쪽에 추가)</td>
      <td style="text-align: center">(B - 1) \/ 10 (오른쪽의 1을 제거)</td>
    </tr>
  </tbody>
</table>

<p>이 때 A에서 B로 갈 때는 언제 어느 연산을 써야 하는지 확실치 않지만 (제가 놓친 것일 수도 있습니다. 혹여나 다른 조건이 있다면 알려주시면 감사하겠습니다!) B에서 A로 갈 때는 연산을 수행할 수 있는 조건이 확실하다.</p>

<p>B의 경우</p>
<ul>
  <li>연산 1은 무조건 B가 2의 배수일 때만 가능</li>
  <li>연산 2는 무조건 B의 10의 자리가 1일 때만 가능</li>
</ul>

<p>해당 조건에 따라 거꾸로 연산을 반복하고 특정 순간 B가 A가 되면? B-&gt;A 즉 A-&gt;B가 가능한거다. 
A와 B가 딱 들어맞지 않고 중간에 연산을 할 수 없는 조건이거나 B&lt;A의 상황이 되면 두 연산으로 도달할 수 없는 것이니까 <code class="language-plaintext highlighter-rouge">-1</code>을 출력하면 된다.</p>

<p>특정 조건에 맞으면 무조건 그 연산을 수행하면 되므로 그리디 알고리즘을 사용해보았다.
<br /><br /><br /></p>
<h1 id="입력">입력</h1>
<hr />

<p>A와 B를 입력받는다. 
$1 &lt;= A &lt;= B &lt;= 10^9$까지이므로 int 범위 A와 B를 정의하고 바로 입력을 받는다.</p>

<pre><code class="language-C++">include &lt;iostream&gt;
using namespace std;

int main(){
	int A, B;
	cin &gt;&gt; A &gt;&gt; B;
}
</code></pre>
<p><br /><br /><br /></p>

<h1 id="처리--출력">처리 &amp; 출력</h1>
<hr />

<p>이후 B에서 A로 도달할 때까지 두 연산을 조건에 맞게 계속 반복해야 한다. 
몇 번 반복해야 할 지 명확하지 않으므로 while 반복을 수행한다. 
반복 종료 조건은 연산 중에 B가 A보다 작아지거나 연산이 실패할 경우이다.</p>

<p>끝 자리가 1이면서 2로 나누어지는 경우는 없으므로 로직을 간단하게 if-else로 처리한다.
연산이 실패한 경우 더 이상 반복할 필요가 없으므로 반복을 종료한다.</p>

<p>이후 출력 시 연산을 실제 수행했으므로 <code class="language-plaintext highlighter-rouge">a==b</code> 조건만 체크해주면 된다.
출력 시 경로가 있다면 연산 횟수에 <code class="language-plaintext highlighter-rouge">+1</code>을 하는 것을 주의하자.
<br /><br /><br /></p>

<h3 id="정답-코드">정답 코드</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#include &lt;iostream&gt;
using namespace std;

void CalcAtoB(int a, int b){
	int cnt = 0;

	while(a &lt; b){
		if(b % 10 == 1) { // 10의 자리가 1이면
		    b = (b-1)/10;
		}
		else if(b % 2 == 0) // 2로 나누어 떨어지면
			b = b / 2;
		else // 두 조건 둘 다 만족하지 않는 순간이 하나라도 있으면 A -&gt; B 성립 X
			break;
		cnt++;
	}
	
	cout &lt;&lt; (a==b ? cnt+1 : -1); // break;로 빠진 경우 a==b일 수가 없다.
}

int main(){
	int A, B;
	cin &gt;&gt; A &gt;&gt; B;

	CalcAtoB(A, B);
}
</code></pre></div></div>
<p><br /><br /><br /></p>

<h1 id="기타">기타</h1>
<hr />

<p>맨 처음에 그리디 방법이 먼저 생각났는데 이 문제가 이렇게 쉽게 풀린다고? 이 경우 이런 조건을 다 해결할 수 있을까? 라는 의구심에 빠져서 시도도 안 해보고 계속 고민만 하고 있었다.
우선 해보고 고민하는 습관을 들이면 실력 향상에 도움이 더 될 것 같다.</p>

<p>또한 문제에 대해서 여러 가지 방면 (이 문제의 경우 거꾸로 접근하는 방법)으로 
조금만 생각을 비틀어서, 새로운 관점에서 보는 사고를 연습해보도록 하자.</p>

<p>다른 사람들은 queue나 BFS 그래프 등등을 사용하더라.
개인적으론 해당 방법으로 푸는 것이 잘 생각나진 않았지만 다른 문제를 통해 해당 알고리즘도 학습하도록 하자!</p>]]></content><author><name>Mellow1213</name></author><category term="boj" /><summary type="html"><![CDATA[그리디 알고리즘을 이용하여 간단하게 풀 수 있는 문제.]]></summary></entry><entry><title type="html">[BOJ][Silver II] 15663번: N과 M(9)</title><link href="https://mellow1213.github.io//boj/codding-test-00/" rel="alternate" type="text/html" title="[BOJ][Silver II] 15663번: N과 M(9)" /><published>2024-10-11T00:00:00+00:00</published><updated>2024-10-11T00:00:00+00:00</updated><id>https://mellow1213.github.io//boj/codding-test-00</id><content type="html" xml:base="https://mellow1213.github.io//boj/codding-test-00/"><![CDATA[<p><a href="https://www.acmicpc.net/problem/15663">문제 바로가기</a></p>

<h2 id="풀이-방법">풀이 방법</h2>

<p>전형적인 백 트래킹 문제 중 하나</p>

<p>문제에서 N의 자연수 중에서 M개를 고르는, $nPm$의 문제이다.
입력 수 중에 중복된 수가 있을 수 있으며 같은 수를 여러번 골라도 된다.
사전 순 출력, 중복  순열 X의 조건을 생각하자.</p>

<p>N개의 공이 있는 주머니에서 M개의 공을 뽑는 <strong>순서</strong>에 대한 경우를 모두 출력하면 되는 것이다.</p>

<h2 id="입력-처리">입력 처리</h2>

<p>처음엔 입력 값을 처리해보자.
입력 받을 것
자연수 N, M -&gt; <code class="language-plaintext highlighter-rouge">int N, M</code>
N개의 수들 -&gt; <code class="language-plaintext highlighter-rouge">vector&lt;int&gt; dataset;</code></p>

<p>그리고 입력받은 값을 사전 순으로 나열해야 하므로 처리하기 편하게 정렬 알고리즘을 사용하자.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;algorithm&gt;</span><span class="cp">
</span>
<span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
	<span class="kt">int</span> <span class="n">N</span><span class="p">,</span> <span class="n">M</span><span class="p">;</span>
	<span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">dataset</span><span class="p">;</span>
	
	<span class="n">cin</span> <span class="o">&gt;&gt;</span> <span class="n">N</span> <span class="o">&gt;&gt;</span> <span class="n">M</span><span class="p">;</span>
	<span class="n">dataset</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">N</span><span class="p">);</span>
	
	<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o">&lt;</span><span class="n">N</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
		<span class="n">cin</span> <span class="o">&gt;&gt;</span> <span class="n">dataset</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
	<span class="p">}</span>

	<span class="n">sort</span><span class="p">(</span><span class="n">dataset</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">dataset</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="처리탐색">처리(탐색)</h2>
<p>그 다음에 모든 수의 경우를 찾는 함수를 써보자.
처음에는 n개의 수를 고르고, 그 다음에 n개에서 수를 고르고, … , 마지막에 M개 번 반복할 때까지 하는 것이다.</p>

<p>그러면 n개의 수를 고르는 동작이 같으므로, loop의 end point가 M개의 수를 고르는 것인 재귀함수를 짜자. 여기서 재귀함수를 쓰는 이유는 모든 경우를 반복문으로 찾는 것이 아닌, 트리 구조를 생각하며 하나하나 탐색하기 위함이다.</p>

<p>dataset 벡터의 경우 함수에서도 사용해야 하는데, 이를 매개변수로 받기엔 쉽지 않다.
그러므로 전역 변수로 빼자.
N과 M도 마찬가지로 계속 체크해야 하므로 전역 변수로 빼자.</p>

<p>Backtrack 함수
Backtrack에서는 주어진 N개의 수열에서 하나의 수를 조건에 맞게 선택할 것이다.
호출의 depth가 M만큼 되었다면, 수열에서 M개 만큼의 수를 고른 것이다.
따라서 계속 호출을 하되 M개에서 멈추는 로직을 짜도록 하자
depth를 계산해야 하므로 파라미터로 <code class="language-plaintext highlighter-rouge">int depth</code>를 넘겨주도록 하자</p>

<h3 id="값-저장">값 저장</h3>
<p>계속해서 탐색을 하면서 track한 수를 저장해야 한 번의 탐색을 마쳤을 때 출력해야 할 수 가 무엇인지 알 것이다.
그렇다고 그 수들을 한꺼번에 저장하고 있는 것도 메모리 낭비이다. 문제에서 단순 출력을 요구하기 때문이다.</p>

<p>따라서 하나의 탐색을 마쳤을 때, 바로 출력하기 위해서 각각의 단계에서 선택한 수를 저장하는 벡터 <code class="language-plaintext highlighter-rouge">vector&lt;int&gt; selection</code>를 만들자.</p>

<h2 id="출력">출력</h2>
<p>M개의 수를 고른 순간 수를 출력하자.
출력은 어떻게 해야할까?
재귀함수의 endpoint때 select 벡터의 값이 하나의 탐색 값이므로 해당 시점에서 select를 출력하자</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;algorithm&gt;</span><span class="cp">
</span>
<span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>

<span class="kt">int</span> <span class="n">N</span><span class="p">,</span> <span class="n">M</span><span class="p">;</span>
<span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">dataset</span><span class="p">;</span>
<span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">selection</span><span class="p">;</span>

<span class="kt">void</span> <span class="nf">Backtrack</span><span class="p">(</span><span class="kt">int</span> <span class="n">depth</span><span class="p">){</span>
	<span class="k">if</span><span class="p">(</span><span class="n">depth</span> <span class="o">&gt;=</span> <span class="n">M</span><span class="p">){</span>
		<span class="k">for</span><span class="p">(</span><span class="k">const</span> <span class="k">auto</span><span class="o">&amp;</span> <span class="n">p</span> <span class="o">:</span> <span class="n">selection</span><span class="p">){</span>
			<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">p</span> <span class="o">&lt;&lt;</span> <span class="sc">' '</span><span class="p">;</span>
		<span class="p">}</span>
		<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>
		<span class="k">return</span><span class="p">;</span>
	<span class="p">}</span>

	<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o">&lt;</span><span class="n">N</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
		<span class="n">selection</span><span class="p">[</span><span class="n">depth</span><span class="p">]</span> <span class="o">=</span> <span class="n">dataset</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
		<span class="n">Backtrack</span><span class="p">(</span><span class="n">depth</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
	<span class="p">}</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="n">main</span><span class="p">(){</span>	
	<span class="n">cin</span> <span class="o">&gt;&gt;</span> <span class="n">N</span> <span class="o">&gt;&gt;</span> <span class="n">M</span><span class="p">;</span>
	<span class="n">dataset</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">N</span><span class="p">);</span>
	<span class="n">selection</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">M</span><span class="p">);</span>
	
	<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o">&lt;</span><span class="n">N</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
		<span class="n">cin</span> <span class="o">&gt;&gt;</span> <span class="n">dataset</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
	<span class="p">}</span>

	<span class="n">sort</span><span class="p">(</span><span class="n">dataset</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">dataset</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>

	<span class="n">Backtrack</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>여기서 Backtrack의 경우 탐색의 깊이인 0만 넘겨주면 된다.
데이터 자체는 전역변수 벡터에서 관리하고 있으므로 알아서 탐색을 진행 할 것이다.
처음 depth 0에서 0번 인덱스를 for문으로 하나하나 돌 것이므로 모든 경우의 수를 탐색한다.</p>

<h3 id="예외-처리">예외 처리</h3>

<p>이때 $nPm$에서 한번 고른 수를 다시 한번 고르는 경우는 없다.
노란 공이 하나밖에 없는 주머니에서 노란 공을 뽑았는데 다음 공이 또 노란색일 수는 없기 때문이다.
따라서 해당 순서에 있는 수를 골랐다고 표기하기 위해 방문을 체크하는 vector를 두자.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;algorithm&gt;</span><span class="cp">
</span>
<span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>

<span class="kt">int</span> <span class="n">N</span><span class="p">,</span> <span class="n">M</span><span class="p">;</span>
<span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">dataset</span><span class="p">;</span>
<span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">selection</span><span class="p">;</span>
<span class="n">vector</span><span class="o">&lt;</span><span class="kt">bool</span><span class="o">&gt;</span> <span class="n">visit</span><span class="p">;</span>

<span class="kt">void</span> <span class="nf">Backtrack</span><span class="p">(</span><span class="kt">int</span> <span class="n">depth</span><span class="p">){</span>
	<span class="k">if</span><span class="p">(</span><span class="n">depth</span> <span class="o">&gt;=</span> <span class="n">M</span><span class="p">){</span>
		<span class="k">for</span><span class="p">(</span><span class="k">const</span> <span class="k">auto</span><span class="o">&amp;</span> <span class="n">p</span> <span class="o">:</span> <span class="n">selection</span><span class="p">){</span>
			<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">p</span> <span class="o">&lt;&lt;</span> <span class="sc">' '</span><span class="p">;</span>
		<span class="p">}</span>
		<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>
		<span class="k">return</span><span class="p">;</span>
	<span class="p">}</span>

	<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o">&lt;</span><span class="n">N</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
		<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">visit</span><span class="p">[</span><span class="n">i</span><span class="p">]){</span> <span class="c1">// 아직 해당 수를 선택하지(뽑지) 않았다면</span>
			<span class="n">selection</span><span class="p">[</span><span class="n">depth</span><span class="p">]</span> <span class="o">=</span> <span class="n">dataset</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
			<span class="n">visit</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span> <span class="c1">// 해당 수를 이미 선택함</span>
			<span class="n">Backtrack</span><span class="p">(</span><span class="n">depth</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
			<span class="n">visit</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span> <span class="c1">// 다시 주머니에 수를 넣기</span>
		<span class="p">}</span>
	<span class="p">}</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="n">main</span><span class="p">(){</span>	
	<span class="n">cin</span> <span class="o">&gt;&gt;</span> <span class="n">N</span> <span class="o">&gt;&gt;</span> <span class="n">M</span><span class="p">;</span>
	<span class="n">dataset</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">N</span><span class="p">);</span>
	<span class="n">selection</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">M</span><span class="p">);</span>
	<span class="n">visit</span><span class="p">.</span><span class="n">assign</span><span class="p">(</span><span class="n">N</span><span class="p">,</span> <span class="nb">false</span><span class="p">);</span> <span class="c1">// N개의 공에 false 표기. 아직 아무 공도 선택되지 않음</span>

	<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o">&lt;</span><span class="n">N</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
		<span class="n">cin</span> <span class="o">&gt;&gt;</span> <span class="n">dataset</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
	<span class="p">}</span>

	<span class="n">sort</span><span class="p">(</span><span class="n">dataset</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">dataset</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="중복-처리">중복 처리</h3>
<p>그리고 문제 조건 중에 같은 수열이 두 번 이상 출력되면 안된다.
그러나 문제의 입력 데이터 중 중복된 수가 있다.
우리는 지금 데이터 자체가 아니라 인덱스 기반으로 탐색을 하고 있으므로
모든 인덱스를 다 출력하면 중복된 데이터의 경우 중복된 수열을 출력할 수 밖에 없지?</p>

<p>여기서, 중복된 수를 피하기 위한 꼼수(?)를 하나 써보자
데이터는 오름차순으로 정렬되어있다. 그러면 중복된 수는 분명 붙어서 출력될 것이다.
갑자기 3번 출력과 7번 출력이 같을 수는 없단 말이다.</p>

<p>그러면 탐색을 할 때, 이전 값과 다음 탐색할 데이터가 같은지만 비교해주면 될 것이다.
값을 저장할 <code class="language-plaintext highlighter-rouge">int temp = 0</code>을 두자. 입력 데이터는 자연수이므로 초기값은 0으로 설정하자.</p>

<p>그리고 각 비교마다 temp와 현재 비교하는 dataset[i]가 같은지 판별해서 같다면(즉, 중복된다면) 탐색을 하지 않는 것으로 하면 된다.</p>

<blockquote>
  <p>[!note] 
이렇게 조건을 기반으로 필요하지 않은 탐색을 진행하지 않는 것을 가지치기(pruning)라고 한다.
이는 BackTracking의 중요 기법 중 하나이다.</p>

  <p>탐색을 하면서 조건에 맞지 않는 탐색의 경우 depth 자체를 파고드는 탐색을 끊어서
필요하지 않은 값을 탐색하는 경우를 사전에 차단하는 것이다.
이를 통해 빠른 탐색 및 불필요한 데이터 및 연산을 막을 수 있다.</p>

  <p>이전의 방문을 했는지, 안했는지에 대해서 판단하는 <code class="language-plaintext highlighter-rouge">!visit[i]</code> 로직 또한 프루닝이다.</p>
</blockquote>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;algorithm&gt;</span><span class="cp">
</span>
<span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>

<span class="kt">int</span> <span class="n">N</span><span class="p">,</span> <span class="n">M</span><span class="p">;</span>
<span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">dataset</span><span class="p">;</span>
<span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">selection</span><span class="p">;</span>
<span class="n">vector</span><span class="o">&lt;</span><span class="kt">bool</span><span class="o">&gt;</span> <span class="n">visit</span><span class="p">;</span>

<span class="kt">void</span> <span class="nf">Backtrack</span><span class="p">(</span><span class="kt">int</span> <span class="n">depth</span><span class="p">){</span>
	<span class="k">if</span><span class="p">(</span><span class="n">depth</span> <span class="o">&gt;=</span> <span class="n">M</span><span class="p">){</span>
		<span class="k">for</span><span class="p">(</span><span class="k">const</span> <span class="k">auto</span><span class="o">&amp;</span> <span class="n">p</span> <span class="o">:</span> <span class="n">selection</span><span class="p">){</span>
			<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">p</span> <span class="o">&lt;&lt;</span> <span class="sc">' '</span><span class="p">;</span>
		<span class="p">}</span>
		<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>
		<span class="k">return</span><span class="p">;</span>
	<span class="p">}</span>

	<span class="kt">int</span> <span class="n">temp</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
	<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o">&lt;</span><span class="n">N</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
		<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">visit</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&amp;&amp;</span> <span class="n">temp</span> <span class="o">!=</span> <span class="n">dataset</span><span class="p">[</span><span class="n">i</span><span class="p">]){</span> <span class="c1">// 이전 데이터와 중복되지 않는다면</span>
			<span class="n">temp</span> <span class="o">=</span> <span class="n">dataset</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> <span class="c1">// 다음 비교를 위해 temp 최신화</span>
			<span class="n">selection</span><span class="p">[</span><span class="n">depth</span><span class="p">]</span> <span class="o">=</span> <span class="n">dataset</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
			<span class="n">visit</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
			<span class="n">Backtrack</span><span class="p">(</span><span class="n">depth</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
			<span class="n">visit</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
		<span class="p">}</span>
	<span class="p">}</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="n">main</span><span class="p">(){</span>	
    <span class="n">ios_base</span><span class="o">::</span><span class="n">sync_with_stdio</span><span class="p">(</span><span class="nb">false</span><span class="p">);</span> <span class="c1">// 빠른 입출력</span>
    <span class="n">cout</span><span class="p">.</span><span class="n">tie</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 출력의 경우만 많으므로 cout만 tie를 처리해주었다.</span>
    
	<span class="n">cin</span> <span class="o">&gt;&gt;</span> <span class="n">N</span> <span class="o">&gt;&gt;</span> <span class="n">M</span><span class="p">;</span>
	<span class="n">dataset</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">N</span><span class="p">);</span>
	<span class="n">selection</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">M</span><span class="p">);</span>
	<span class="n">visit</span><span class="p">.</span><span class="n">assign</span><span class="p">(</span><span class="n">N</span><span class="p">,</span> <span class="nb">false</span><span class="p">);</span>

	<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o">&lt;</span><span class="n">N</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
		<span class="n">cin</span> <span class="o">&gt;&gt;</span> <span class="n">dataset</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
	<span class="p">}</span>

	<span class="n">sort</span><span class="p">(</span><span class="n">dataset</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">dataset</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>
	<span class="n">Backtrack</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>(빠른 출력을 위해 뒤늦게 동기화 처리를 해주었다.)</p>

<p>여기서 왜? int temp를 함수 내에 지역 변수로 선언했는가?
계속 데이터를 체크하기 위해 밖에 빼야 할 것 같은데… 하는 사람도 있을 것이다.</p>

<p>그러나 컴퓨터구조를 공부하다보면 왜 temp 변수를 지역 변수로 선언했는지 알 것이다.
먼저 재귀함수가 <strong>Stack 메모리</strong>에 어떻게 들어가는지 보자.</p>

<p>![[IMG-20241011095149599.png]]</p>

<p>지역 변수들은 각 <strong>함수</strong>별로 스택에 저장된다. 같은 식별자 temp를 사용하지만, 메모리 상으로는 별개의 변수인 것이다.
depth 0의 temp, depth 1의 temp는 각각 다른 함수이므로 식별자 또한 다른 것이다. 그리고 depth를 돌다가 다시 반환되서 돌아오면 이전 depth의 temp는 이전 값을 메모리에 저장한 채로 있는 것이다.</p>

<p><code class="language-plaintext highlighter-rouge">temp</code> 변수가 <code class="language-plaintext highlighter-rouge">dataset[i]</code> 값을 저장한 이유는 같은 depth에서 중복 수열을 만들지 않기 위해서이다. 
아까 언급한 대로 <code class="language-plaintext highlighter-rouge">dataset</code> 배열을 오름차순으로 정렬했기 때문에 같은 값을 갖는 수가 있다면 바로 옆에 위치할 것이다. <code class="language-plaintext highlighter-rouge">temp</code>값이 이전 배열의 마지막 값을 저장하고 있으므로 같은 depth에서 체크하면 중복 수열을 만들지 않게 되는 것이다.</p>

<p>그리고 해당 로직을 통해 중복을 다 체크하고 이전 depth로 돌아왔을 때, 해당 depth에서는 별개의 함수 스택에 있었으므로 해당 depth의 temp값에 저장된 값을 토대로 진행하는 것이다.</p>

<p>![[IMG-20241010115251271.png]]
백트래킹 및 재귀함수를 활용한 프루닝에 대해 제대로 이해할 수 있는 문제였다.</p>

<h1 id="기타-주의-점">기타 주의 점</h1>
<p>이번 문제를 풀면서 처음에 선택하는 변수의 이름을 지을 때 <code class="language-plaintext highlighter-rouge">cache</code>, <code class="language-plaintext highlighter-rouge">select</code> 등등 이름을 지었다.</p>

<p>cache는 문제의 정의에 맞지 않고,
select는 이미 정의된 예악어라 컴파일 에러를 내보냈다.
(소켓통신 관련 네트워크 함수라고 한다)</p>

<p>지금 생각에도 뭔가 더 좋은 이름이 있을 것 같은데,,, 하면서 글을 쓰고 있다.  <br />
(좋은 이름이 있다면 추천 바랍니다 ^-^;;)</p>

<p>변수 이름을 정할 때도 전반적인 전산학 및 언어에 대한 지식이 있어야 함을 다시 상기시켰던 에러들이었다.</p>]]></content><author><name>Mellow1213</name></author><category term="boj" /><summary type="html"><![CDATA[전형적인 back-tracking 문제 중 하나]]></summary></entry><entry><title type="html">[Algorithm] 정렬 알고리즘 이론</title><link href="https://mellow1213.github.io//algorithm/sort-algorithm-00/" rel="alternate" type="text/html" title="[Algorithm] 정렬 알고리즘 이론" /><published>2024-10-07T00:00:00+00:00</published><updated>2024-10-07T00:00:00+00:00</updated><id>https://mellow1213.github.io//algorithm/sort-algorithm-00</id><content type="html" xml:base="https://mellow1213.github.io//algorithm/sort-algorithm-00/"><![CDATA[<h1 id="정렬-알고리즘">정렬 알고리즘</h1>

<p>정렬 알고리즘(sorting algorithm)이란 원소들을 번호순이나 사전 순서와 같이 일정한 순서대로 열거하는 알고리즘이다.</p>

<p>즉 어떤 데이터(혹은 원소)들이 주어졌을 때 이를 정해진 순서대로 나열하는 문제.
<br /><br /></p>

<p>효율적인 정렬은 탐색이나 병합 알고리즘처럼 (정렬된 리스트에서 바르게 동작하는) 다른 알고리즘을 최적화하는 데 중요하며 데이터의 정규화나 의미있는 결과물을 생성하는 데 유용히 쓰인다.</p>

<h2 id="정렬-알고리즘을-사용하는-이유">정렬 알고리즘을 사용하는 이유</h2>
<h3 id="정렬-데이터의-특징">정렬 데이터의 특징</h3>

<p>실제 컴퓨터 분야에서 사용하는 데이터의 경우 숫자의 순서나 어휘의 순서대로 정렬한 다음 사용해야 되는 경우가 거의 항상 발생하는데 이걸 얼마나 효과적으로 해결할 수 있느냐가 정렬 문제의 핵심이고 정렬 알고리즘의 효율을 따지는 데 제일 중요한 요소가 된다.</p>

<p>이미 정렬된 데이터의 특징은 어떤 값을 임의로 집었을 때 해당 위치 오른쪽에는 무조건 그것보다 크거나 같은 값, 왼쪽에는 무조건 그것보다 작거나 같은 값이 있다는 것이다.</p>

<p>따라서 탐색을 할 때 컴퓨터가 찾고자 하는 값보다 임의로 집은 값이 <strong>작다면</strong> 다음 탐색에는 오른쪽만 보면 된다.</p>

<p>컴퓨터가 어떤 값을 집어올리는 위치가 후보군의 가운데인 탐색 알고리즘이 이진 탐색 알고리즘이다. </p>

<p>이진 탐색 알고리즘은 최악의 경우라도 $log⁡n$의 성능을 보이는데 예를 들어 43억 개의 <strong>정렬된</strong> 자료가 들어있는 데이터에서 어떤 값을 찾아야 할 때 최악의 비교 횟수(찾는 값이 없는 경우)는 겨우 32회에 불과하다. 33회 비교시에는 약 86억 개의 자료를 탐색할 수 있다.</p>

<p>컴퓨터에서 정렬을 수행하는 이유 중 하나는 바로 이 이진 탐색이 가능한 데이터를 만들기 위해서이다. 이는 알고리즘 문제를 풀다 보면 확실히 느끼는 될 부분이다.</p>

<h3 id="정렬-알고리즘-성능">정렬 알고리즘 성능</h3>

<p>다른 알고리즘과 마찬가지로 Big-O로 표현되는 시간 복잡도가 정렬 알고리즘의 성능을 나타내는 데 제일 중요하다.</p>

<p>정렬 알고리즘은 입력받는 데이터의 상태에 따라 평균, 최선, 최악의 경우의 시간 복잡도가 다르다.</p>

<p><img src="/Attatchments/241007/sort-algorithm-Big-O.png" alt="" /></p>

<p>정렬 알고리즘의 경우 최선의 시간복잡도가 $O(nlogn)$이다.
아직 $O(n)$의 시간 복잡도 정렬 알고리즘을 찾지 못한 것이 아니라 수학적으로 증명했을 때 이 정렬 알고리즘 문제의 구조 상 제일 빠른 알고리즘이 $O(nlogn)$인 것이다.</p>

<p>이 외에는 메모리의 탐색 횟수, 데이터의 교환 횟수 등등과
안정/불안정성이 있다.</p>

<p>모든 경우에 최선을 내는 알고리즘은 없으므로 각 알고리즘의 성능 및 특징을 잘 아는 것이 중요하다.</p>

<h3 id="안정-정렬-불안정-정렬">안정 정렬? 불안정 정렬?</h3>

<p>안정 정렬(stable sort)은 중복된 값을 입력 순서와 동일하게 정렬한다. 
불안정 정렬(unstable sort)은 정렬을 한 뒤에도 기존의 순서 유지가 보장되지 않을 수도 있는 정렬이다. 섞일 수도 있고 아닐 수도 있다.</p>

<p>좋은 예시가 있어서 꺼무위키에서 임시로 이미지를 빌려왔다.
// 추후에 더 좋은 이미지를 준비할게요!</p>

<p>안정 정렬의 경우에는 기존의 시간 순으로 정렬했던 순서는 지역명으로 재정렬하더라도 기존 순서가 그대로 유지된 상태에서 정렬이 이뤄진다. 그러나 불안정 정렬의 경우에는 시간순으로 정렬한 값을 지역명으로 재정렬하면 기존의 정렬 순서는 무시된 채 모두 뒤죽박죽 뒤섞이고 만다.</p>

<p><img src="https://i.namu.wiki/i/eQSUWF3e97XxPv1T7GtWpFPBKjc5Nuwx1xypw_ZioU_NsX2RI07cWHY79Vo7J9GJUHu6_SHrnt7sy2ToqaeMpGMFx864iTpAZaA-vnG1k5ZYhLgYziDmexexPkJHycy9JNgCsPG36mutvt7d8s7mwA.webp" alt="5-17-4" /></p>

<p>이처럼 입력값이 유지되는 안정 정렬 알고리즘이 불안정 정렬 알고리즘보다 많은 상황에서 사용할 수 있을 것이다.</p>]]></content><author><name>Mellow1213</name></author><category term="algorithm" /><category term="algorithm" /><category term="sort" /><summary type="html"><![CDATA[정렬 알고리즘에 대한 이론 정리]]></summary></entry></feed>