<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>daily_j.log</title>
        <link>https://velog.io/</link>
        <description>다시 시작합니다 :)</description>
        <lastBuildDate>Mon, 25 Dec 2023 11:23:30 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>daily_j.log</title>
            <url>https://velog.velcdn.com/images/daily_j/profile/3ebcbe82-6952-436e-990e-d6b6540e1b33/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. daily_j.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/daily_j" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Java] 문자 정리 - split(), replace(), trim()]]></title>
            <link>https://velog.io/@daily_j/Java-%EB%AC%B8%EC%9E%90-%EC%A0%95%EB%A6%AC-split-replace-trim</link>
            <guid>https://velog.io/@daily_j/Java-%EB%AC%B8%EC%9E%90-%EC%A0%95%EB%A6%AC-split-replace-trim</guid>
            <pubDate>Mon, 25 Dec 2023 11:23:30 GMT</pubDate>
            <description><![CDATA[<h2 id="이-글을-작성하는-이유">이 글을 작성하는 이유</h2>
<ul>
<li>문자열을 나눠서 문제를 풀이하는 경우가 굉장히 많다. 특히, 문자열을 단어 하나 단위로 쪼개거나, 띄어쓰기, 특수문자 등을 기준으로 잘라 사용해야 하는 경우가 많은데, 여기서는 활용도가 높은 split() 위주로 활용하여 단어를 나누는 방법에 대해 서술할 예정이다.</li>
</ul>
<h3 id="문자-하나를-가져올-때">문자 하나를 가져올 때</h3>
<pre><code>public class stackPracticeQuestion {
    public static void checkParenthesis(String str){
        Stack stack = new Stack();
        boolean checkFlag = true;

        for (String s: str.split(&quot;&quot;)){
            if (s.equals(&quot;(&quot;)) {
                stack.push(s);
            } else {
                if (stack.isEmpty()){
                    checkFlag = false;
                    break;
                } else {
                    stack.pop();
                }
            }
        }
 }</code></pre><ul>
<li><p>for (String s: str.split(&quot;&quot;)) 를 기준으로 문자를 하나씩 잘라서 확인할 수 있다.</p>
</li>
<li><p>이외에도 tocharArray()로 변환하여 한 문자씩 가지고 올 수 있다. (다만, char로 문자형태가 바뀌긴 할 것이다.)</p>
<pre><code>String str = &quot;ABCDE&quot;;
char[] arr = str.toCharArray();
for (int i = 0; i &lt;arr.length; i++){
  System.out.println(arr[i]+&quot; &quot;);
 }</code></pre></li>
</ul>
<h4 id="참고-charat">(참고) charAt()</h4>
<ul>
<li>String으로 저장된 문자열 중에서 한 글자만 선택해서 char 타입으로 변환할 수 있는 기능을 가진다.<pre><code>String str = &quot;안녕하세요&quot;;
char c = str.charAt(0);
System.out.println(c); // &quot;안&quot;</code></pre></li>
</ul>
<h3 id="띄어쓰기를-기준으로-할-때">띄어쓰기를 기준으로 할 때</h3>
<pre><code>String[] arStr = &quot;ABC DEF&quot;.split(&quot;\\s&quot;);</code></pre><ul>
<li>\\s는 공백을 의미하는데, 이러한 정규식을 사용하여 띄어쓰기 한 칸을 기준으로 단어를 분리할 수 있다.</li>
<li>또한, 한 칸 이상의 공백을 제거하기 위해서 아래와 같은 코드를 사용할 수 있다. <pre><code>String[] arStr = &quot;ABC   DEF&quot;.split(&quot;\\s+&quot;);</code></pre></li>
</ul>
<h3 id="그-외-replace-trim">그 외 (replace, trim)</h3>
<ul>
<li><p>replace는 한 문자를 다른 문자로 치환한다는 뜻으로 아래와 같이 특수문자를 공백 등으로 변경하고 싶을 때 사용할 수 있다.</p>
<pre><code>s = s.replace(&quot;?&quot;,&quot; &quot;);</code></pre></li>
<li><p>trim은 양 옆 공백을 지우고 싶을 때 사용할 수 있다.</p>
<pre><code>s = s.trim();</code></pre></li>
</ul>
<p>종합하면 아래와 같이 코드를 구성할 수 있다.</p>
<pre><code>public class Solution {
    public statuc void main(Stinrg[] args) {
        String s = &quot;?ab???c &quot;; 
        s = s.replace(&quot;?&quot;,&quot; &quot;); // &quot; ab   c &quot;
        s = s.trim(); // &quot;ab   c&quot;
        String[] answer = s.split(&quot;\\s+&quot;); // {ab , c}
    }
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] int <> String 변환]]></title>
            <link>https://velog.io/@daily_j/Java-int-String-%EB%B3%80%ED%99%98</link>
            <guid>https://velog.io/@daily_j/Java-int-String-%EB%B3%80%ED%99%98</guid>
            <pubDate>Mon, 25 Dec 2023 10:54:37 GMT</pubDate>
            <description><![CDATA[<h2 id="글-작성-목적">글 작성 목적</h2>
<ul>
<li>문제를 풀다보면, 자료형을 변환해야하는 일이 자주 발생한다. 특히 문자를 숫자형으로 변환하는 일들이 자주 발생하는데 이를 미리 정리하여 추후 헷갈리는 일이 없도록 할 예정이다.</li>
</ul>
<h2 id="string---int">String -&gt; int</h2>
<h3 id="integerparseint">Integer.parseInt</h3>
<ul>
<li><p>해당 함수를 사용할 경우 문자열을 기본 정수 (int)로 변환해준다.</p>
</li>
<li><p>parseInt(string, radix);</p>
</li>
</ul>
<p>Parameter</p>
<ul>
<li>string: 숫자로 변환하고 싶은 문자열</li>
<li>radix: string 문자열을 읽을 진법</li>
</ul>
<pre><code>public class StringToInt {    
    public static void main(String[] args) {        
        String str1 = &quot;123&quot;;        
        String str2 = &quot;0xF&quot;;         

        int intValue1 = Integer.parseInt(str1);        
        int intValue2 = Integer.parseInt(str2, 16);     

        System.out.println(intValue1); // 123
        System.out.println(intValue2); // 15
    }
}
</code></pre><ul>
<li>예시1. &quot;123&quot;이라는 String을 10진법 Int로 읽어온다.</li>
<li>예시2. &quot;0xF&quot;라는 String을 16진법으로 생각하여 10진법 Int로 변환한다.</li>
</ul>
<h3 id="참고-integervalueof">(참고) Integer.valueOf()</h3>
<ul>
<li>해당 함수를 사용할 경우 문자열을 정수 객체 (Integer Object)로 변환한다. 즉, int가 아닌 Integer가 필요할 때 사용하면 된다. 이는 Integer(Integer.parseInt(s))와 동일한 결과값을 출력할 것이다.</li>
</ul>
<h2 id="int---string">int -&gt; String</h2>
<h3 id="integertostring-stringvalueof">Integer.toString(), String.valueOf()</h3>
<ul>
<li>Integer 클래스 혹은 String 클래스 내에 있는 기능을 사용하여 숫자를 문자로 변환할 수 있다.</li>
</ul>
<pre><code>public class IntToString {
    public static void main(String[] args) {
        int intValue1 = 1234;
        int intValue2 = 1234;

        String str1 = Integer.toString(intValue1);
        String str2 = String.valueOf(intValue2);

        System.out.println(str1); // 1234
        System.out.println(str2); // 1234
    }
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[HashTable 정리]]></title>
            <link>https://velog.io/@daily_j/HashTable-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@daily_j/HashTable-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Thu, 21 Dec 2023 02:49:51 GMT</pubDate>
            <description><![CDATA[<h1 id="hash-table이란">Hash Table이란?</h1>
<p><img src="https://velog.velcdn.com/images/daily_j/post/3f3cd5ad-678c-4fab-a0cd-bb7ac6989d3f/image.png" alt=""></p>
<h2 id="개념-정리">개념 정리</h2>
<p>해시 테이블은 (Key, Value)로 데이터를 저장하는 자료구조 중 하나로 빠르게 데이터를 검색할 수 있는 자료구조이다. 해시 테이블이 빠른 검색속도를 제공하는 이유는 내부적으로 배열(버킷)을 사용하여 데이터를 저장하기 때문이다. 해시 테이블은 각각의 Key값에 해시함수를 적용해 배열의 고유한 index를 생성하고, 이 index를 활용해 값을 저장하거나 검색하게 된다. 여기서 실제 값이 저장되는 장소를 버킷 또는 슬롯이라고 한다.</p>
<p>그렇다면 이를 정리하는 해시 함수가 존재할 것이다. 예를 들어, 나눗셈 결과의 나머지를 해시 함수로 사용할 수 있을 것이다. (이를 division Method라고도 부른다.) 그 외에도 다양한 함수들이 존재하는데, 여기서의 공통적인 문제는 해시함수가 같은 값을 출력하는 경우 어떻게 대처할 것인지다.</p>
<p>이렇게 값이 충돌하는 경우를 &#39;해시충돌&#39;이라고 부르며, 이 경우를 해결할 수 있는 방법이 많이 알려져 있다. 크게는 분리 연결법과 개방 주소법이 있는데 이에 대한 설명은 추후 진행할 예정이다.</p>
<h2 id="hash-map-vs-hashtable">Hash Map vs. HashTable</h2>
<p>자바에는 Map Inferface를 구현한 자료구조로 HashMap과 HashTable가 존재하는데, 둘의 차이를 살펴보자.</p>
<pre><code>public class myHashTableStudy {
    public static void main(String args[]){
        Hashtable&lt;String, Integer&gt; ht = new Hashtable();

        ht.put(&quot;key1&quot;, 10);
        ht.put(&quot;key2&quot;, 20);

        HashMap&lt;Integer, Integer&gt; hm = new HashMap&lt;&gt;();
        hm.put(0,10);
        System.out.println(hm.get(0));

        // ht.put(null, 999) : Error Occured.
        hm.put(null, -999);
        System.out.println(hm.get(null));


}</code></pre><p>가장 단순한 차이로는 key 값에 null을 쓸 수 있는지에 있다. HashTable에는 null 값을 key로 사용할 수 없으며, Map에서는 가능하다. 그 외에도 Thread-Safe 여부에 따라 사용성이 달라지는데, 이는 더 공부한 이후에 추가로 작성할 예정이다. 이해한 만큼만 쓰자면, 병렬 처리를 하면서 자원의 동기화를 고려할 때는 해시테이블(HashTable)을, 병렬 처리를 하지 않거나 자원의 동기화를 고려하지 않을 때는 해시맵(HashMap)을 사용하면 된다.</p>
<h2 id="어디서-사용하는가">어디서 사용하는가?</h2>
<h3 id="예제1-array-값-비교하기">예제1. Array 값 비교하기</h3>
<pre><code>    public static void solution(int[] arr1, int[] arr2){
        Hashtable&lt;Integer, Integer&gt; ht = new Hashtable&lt;&gt;();
        for (int i = 0; i &lt; arr1.length; i++) {
            ht.put(arr1[i],arr1[i]);
        }

        for (int i = 0; i &lt; arr2.length; i++) {
            if (ht.containsKey(arr2[i])){
                System.out.print(&quot;True &quot;);
            } else {
                System.out.print(&quot;False &quot;);
            }
        }
    }</code></pre><p>HashTable에 arr1의 데이터를 저장한 후, for문을 통해 arr2에 arr1과 같은 값이 있는지를 containsKey()를 통해 확인한다.</p>
<h3 id="예제2-숫자-조합하기">예제2. 숫자 조합하기</h3>
<pre><code>    public static int[] targetCheck(int[] numbers, int target){
        int[] result = new int[2];
        Hashtable&lt;Integer, Integer&gt; ht = new Hashtable&lt;&gt;();

        for (int i = 0; i &lt; numbers.length; i++){
            if (ht.containsKey(numbers[i])){
                result[0] = ht.get(numbers[i]);
                result[1] = i;
                return result;
            }
            ht.put(target - numbers[i], i);
        }
        return null;
    }</code></pre><ol>
<li>HashTable에 target - 처음 숫자 값을 키로 저장한다.</li>
<li>만약 키 값과 일치하는 숫자를 찾는다면, 그 숫자와 함께 HashTable에 저장했었던 처음 숫자 값의 인덱스를 같이 반환한다.
이를 통해 O(n)으로 문제를 해결할 수 있게 된다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[Array 정리]]></title>
            <link>https://velog.io/@daily_j/Array-%EC%A0%95%EB%A6%AC-6g8gzntf</link>
            <guid>https://velog.io/@daily_j/Array-%EC%A0%95%EB%A6%AC-6g8gzntf</guid>
            <pubDate>Thu, 21 Dec 2023 02:32:20 GMT</pubDate>
            <description><![CDATA[<h1 id="array란">Array란?</h1>
<h2 id="개념-정리">개념 정리</h2>
<p><img src="https://velog.velcdn.com/images/daily_j/post/e20e21c8-af30-4c4c-a7d4-5d92776603d6/image.png" alt=""></p>
<p> Array는 우리가 직관적으로 알고 있는 표 / 테이블과 유사하다. 여기서는 조금 더 언어를 명확히 하여 자료구조의 의미를 써보겠다. Array란 각 데이터와 인덱스가 1:1로 대응하는 구조를 의미한다. 그래서, 데이터와 함께 &#39;인덱스&#39;라는 것이 반드시 존재한다.</p>
<p> 이는 추후 설명할 Linked List와 비교하면 그 차이가 더 두드러진다. Array는 인덱스가 있어 값의 위치를 바로 확인할 수 있는 반면, Linked List는 인덱스가 없어 값을 탐색하려면, Head부터 쭉 찾아봐야한다는 단점이 있다. 아까 위에서 &quot;각 데이터와 인덱스가 1:1로 대응하는 구조&quot;라고 한 말이 바로 이 뜻이다. 결국 데이터에 맞는 인덱스가 있기 때문에 &#39;탐색&#39;이 쉽다고 이해하면 좋을 것이다.</p>
<p> 그러면 반대로 인덱스를 써서 안 좋은 점도 있을 것이다. 인덱스를 쓰게 되면 데이터를 추가/삭제할 떄 인덱스를 다시 할당해야하는 문제점이 생긴다. 예를 들어 보자. {1,2,3,4,5}이라는 배열이 있다고 하자. 이 경우 &#39;2&#39;라는 데이터를 삭제하면, 남은 3,4,5의 인덱스 값을 모두 바꿔줘야 하는 문제가 생긴다. (물론 배열의 size도 변경해야 한다.) 그렇기 때문에, 추가/삭제가 빈번한 경우 다른 자료구조를 쓰는 것이 적절할 것이다.</p>
<h2 id="주요-기능">주요 기능</h2>
<p>주요 기능은 단순하게 add, remove만 확인해보고, 아래에서 이를 다양하게 활용하는 방법에 대해 알아보자.</p>
<pre><code>import java.util.ArrayList;
import java.util.Arrays;

public class myArrayStudy {
    public static void main(String[] args){
        // Basics
        System.out.println(&quot;== 1차원 배열 ==&quot;);
        int[] arr = {1,2,3,4,5};
        for (int item : arr){
            System.out.println(&quot;item = &quot; + item);
        }

        System.out.println(&quot;== 2차원 배열 ==&quot;);
        int[][] arr2 = {{1,2,3},{4,5,6}};
        System.out.println(arr2[0][1]);

        for (int[] row: arr2){
            for (int item: row){
                System.out.println(&quot;item = &quot; + item);
            }
        }

        // ArrayList
        System.out.println(&quot;== Array List 활용 ==&quot;);
        ArrayList list1 = new ArrayList(Arrays.asList(1,2,3));
        System.out.println(&quot;list1 = &quot; + list1);
        list1.add(4);
        list1.add(5);
        System.out.println(&quot;list1 = &quot; + list1);
        list1.remove(2);
        System.out.println(&quot;list1 = &quot; + list1);
        list1.remove(Integer.valueOf(2));
        System.out.println(&quot;list1 = &quot; + list1);

        System.out.println(&quot;== Array List 2D ==&quot;);
        ArrayList list2d = new ArrayList();
        ArrayList list1d1 = new ArrayList(Arrays.asList(1,2,3));
        ArrayList list1d2 = new ArrayList(Arrays.asList(4,5,6));
        list2d.add(list1d1);
        list2d.add(list1d2);
        System.out.println(&quot;list2d = &quot; + list2d);

    }
}
</code></pre><p>여기서 주목할 점 몇 가지를 살펴보자. </p>
<ul>
<li><p>Array 출력방법
Array를 출력할 때는 for문을 돌려서 가져오자. </p>
<pre><code>      // Basics
      System.out.println(&quot;== 1차원 배열 ==&quot;);
      int[] arr = {1,2,3,4,5};
      for (int item : arr){
          System.out.println(&quot;item = &quot; + item);
      }

      System.out.println(&quot;== 2차원 배열 ==&quot;);
      int[][] arr2 = {{1,2,3},{4,5,6}};
      System.out.println(arr2[0][1]);

      for (int[] row: arr2){
          for (int item: row){
              System.out.println(&quot;item = &quot; + item);
          }
      }</code></pre></li>
<li><p>ArrayList 활용</p>
<pre><code>      System.out.println(&quot;== Array List 활용 ==&quot;);
      ArrayList list1 = new ArrayList(Arrays.asList(1,2,3));
      System.out.println(&quot;list1 = &quot; + list1);
      list1.add(4);
      list1.add(5);
      System.out.println(&quot;list1 = &quot; + list1);
      list1.remove(2);
      System.out.println(&quot;list1 = &quot; + list1);
      list1.remove(Integer.valueOf(2));
      System.out.println(&quot;list1 = &quot; + list1);</code></pre></li>
</ul>
<p>자바의 ArrayList()를 활용하여 다양한 기능을 사용하며, 이때 값을 넣기 위해서 Arrays.asList()를 사용하는 것을 참고하자. 또한, 값을 제거하고 싶을 때 reemove()를 쓰면 인덱스 기준으로, remove(Integer.valueOf())를 쓰면 값 (여기서는 정수 값)을 기준으로 값을 제거할 수 있다는 점을 참고하자.</p>
<h2 id="어디서-사용하는가">어디서 사용하는가?</h2>
<h3 id="예제1-값-찾기">예제1. 값 찾기</h3>
<p>이전의 출력 방법을 응용하여 for문 기반의 값을 찾을 수 있다. 이때 int[]로도 구현하여 풀이하는 것이 주목하자.</p>
<pre><code>public class arrayPracticeQuestions {
    public static void main (String[] args){
        int[] arr2 = {1,1,100,1,1,1,100};
        int target = 100;
        int idx = -1;
        for (int i = 0; i &lt; arr2.length; i++){
            if (arr2[i] == target){
                idx = i;
            }
        }
        if (idx == -1){
            System.out.println(&quot;No target here.&quot;);
        } else {
            System.out.println(&quot;idx = &quot; + idx);
        }
    }
}</code></pre><h3 id="예제2-peek-찾기">예제2. Peek 찾기</h3>
<p>양 옆의 값보다 큰 수를 찾는 방법이다. 양끝 값을 별도로 처리해준 것을 참고하자.</p>
<pre><code> public class arrayPracticeQuestions {
    public static void main (String[] args){
         int[] arr4 = {3,1,2,6,2,2,5,1,9,10,1,11};

        if (arr4[1] &lt; arr4[0]){
            System.out.println(arr4[0]);
        }

        for (int i = 1; i &lt; arr4.length-1; i ++)
            if (arr4[i] &gt; arr4[i-1] &amp; arr4[i] &gt; arr4[i+1]){
                System.out.println(arr4[i]);
            }

        if (arr4[arr4.length-2] &lt; arr4[arr4.length-1]){
            System.out.println(arr4[arr4.length-1]);
        }
    }
}
</code></pre><h3 id="예제3-출력-90도-뒤집기">예제3. 출력 90도 뒤집기</h3>
<p>2차원 배열에서 arr[0].length을 사용하면 행의 길이가, arr.length를 사용하면 열의 길이가 나온다는 점에 주목하자. 그 이후 newArr[i][cnt1] = row[i];를 통해 값을 정리해주면 된다.</p>
<pre><code> public class arrayPracticeQuestions {
    public static void main (String[] args){
        int[][] arr7 = {{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}};
        int[][] newArr = new int[arr7[0].length][arr7.length];
        int cnt1 = arr7.length-1;

        for (int[] row: arr7){
            int rowLength = row.length;
            for (int i = 0; i &lt; rowLength; i++){
                newArr[i][cnt1] = row[i];
            }
            cnt1 --;
        }

        for (int[] row: newArr){
            for (int item: row){
                System.out.print(item + &quot; &quot;);
            }
            System.out.println();
        }
    }
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Array: 백준 10818번 최소, 최대]]></title>
            <link>https://velog.io/@daily_j/Array-%EB%B0%B1%EC%A4%80-10818-%EC%B5%9C%EC%86%8C-%EC%B5%9C%EB%8C%80</link>
            <guid>https://velog.io/@daily_j/Array-%EB%B0%B1%EC%A4%80-10818-%EC%B5%9C%EC%86%8C-%EC%B5%9C%EB%8C%80</guid>
            <pubDate>Thu, 21 Dec 2023 02:29:15 GMT</pubDate>
            <description><![CDATA[<ul>
<li>출처: <a href="https://www.acmicpc.net/problem/10818">https://www.acmicpc.net/problem/10818</a></li>
</ul>
<p>Array를 활용하여 최소, 최대 값을 출력하는 문제이다.</p>
<pre><code>import java.io.IOException;
import java.util.Scanner;

public class Q3 {
    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();

        int[] seq = new int[n];

        for(int i = 0; i &lt; n; i++) {
            seq[i] = sc.nextInt();
        }

        int maxInt = Integer.MIN_VALUE;
        int minInt = Integer.MAX_VALUE;

        for (int item: seq){
            if (item &gt;= maxInt){
                maxInt = item;
            } if (item &lt;= minInt){
                minInt = item;
            }
        }

        System.out.print(minInt +&quot; &quot;+ maxInt);

    }
}
</code></pre><p>별도의 코멘트는 없으나, maxInt, minInt가 처음부터 오류없이 들어가게 하려면 MIN_VALUE, MAX_VALUE 등을 활용해야 했다. 숫자의 범위 등에 대해서 다시 체크할 수 있는 좋은 기회였다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Queue / Deque: 백준 1021번 회전하는 큐]]></title>
            <link>https://velog.io/@daily_j/Queue-Deque-1021%EB%B2%88-%ED%9A%8C%EC%A0%84%ED%95%98%EB%8A%94-%ED%81%90</link>
            <guid>https://velog.io/@daily_j/Queue-Deque-1021%EB%B2%88-%ED%9A%8C%EC%A0%84%ED%95%98%EB%8A%94-%ED%81%90</guid>
            <pubDate>Tue, 19 Dec 2023 06:28:33 GMT</pubDate>
            <description><![CDATA[<ul>
<li>출처: <a href="https://www.acmicpc.net/problem/1021">https://www.acmicpc.net/problem/1021</a></li>
</ul>
<h2 id="문제-설명">문제 설명</h2>
<p>결국 제시된 3가지 연산을 이해하는 것이 중요하다.</p>
<ol>
<li><p>첫 번째 원소를 뽑아낸다. 원래 큐의 원소가 a1, ..., ak이었던 것이 a2, ..., ak와 같이 된다.</p>
</li>
<li><p>왼쪽으로 한 칸 이동시킨다. 이 연산을 수행하면, a1, ..., ak가 a2, ..., ak, a1이 된다.</p>
</li>
<li><p>오른쪽으로 한 칸 이동시킨다. 이 연산을 수행하면, a1, ..., ak가 ak, a1, ..., ak-1이 된다.</p>
</li>
</ol>
<p>앞뒤로 값을 한 칸씩 옮기거나 지울 수 있다는 점에서 &quot;Deque&quot;를 떠올릴 수 있다. </p>
<ul>
<li>1번 연산은 결국 removeFirst()</li>
<li>2번 연산은 deque.addLast(deque.removeFirst())</li>
<li>3번 연산은 deque.addFirst(deque.removeLast())</li>
</ul>
<p>의 개념과 연결될 수 있을 것이다.</p>
<h2 id="코드-설명">코드 설명</h2>
<p>1번 연산은 바로 수행하면 되지만, 2,3번 연산은 수행하기 전에 2번 연산에 해당하는지, 3번 연산에 해당하는지 판단할 필요가 있다.</p>
<p>그래서, distance라는 개념을 도입하여 왼쪽까지의 거리, 오른쪽까지의 거리를 계산하였다. 이를 통해 더 거리가 짧은 쪽으로 이동하면 될 것이다.</p>
<pre><code>import java.io.IOException;
import java.util.LinkedList;
import java.util.Scanner;
import java.util.stream.IntStream;

import static java.lang.Math.abs;

public class Q2 {
    public static Integer checkDistance(int item, int target, LinkedList&lt;Integer&gt; deque) {
        int distance = abs(deque.indexOf(item) - deque.indexOf(target));
        int halfIndex = deque.size() / 2;
        if (distance &gt; halfIndex) {
            distance = deque.size() - distance;
        }
        return distance;
    }

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);

        LinkedList&lt;Integer&gt; deque = new LinkedList&lt;Integer&gt;();

        int N = sc.nextInt();
        int M = sc.nextInt();
        int cnt = 0;
        int target = 0;

        IntStream.range(1, N+1).forEach(deque::add);

        int[] seq = new int[M];

        for(int i = 0; i &lt; M; i++) {
            seq[i] = sc.nextInt();
        }

        for (int item: seq){
            target = (int) deque.getFirst();
            int distance = checkDistance(item, target, deque);
            if (distance == 0){
                deque.getFirst();
            } else if (abs(deque.indexOf(item) - deque.indexOf(target)) &lt;= deque.size() / 2) {
                for (int i = 0; i &lt; distance; i++) {
                    deque.addLast(deque.removeFirst());
                }
            } else {
                for (int i = 0; i &lt; distance; i++){
                    deque.addFirst(deque.removeLast());
                }
            }
            cnt += distance;
            deque.removeFirst();
        }
        System.out.println(cnt);
    }
}
</code></pre><h2 id="소감">소감</h2>
<p>처음에 indexOf()를 쓸 수 없다고 생각해서 구현에 시간이 다소 오래 걸렸다. 해당 기능에 대한 숙지가 필요할 것 같다..!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Queue / Deque 정리]]></title>
            <link>https://velog.io/@daily_j/Queue-Deque-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@daily_j/Queue-Deque-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Tue, 19 Dec 2023 06:17:25 GMT</pubDate>
            <description><![CDATA[<h1 id="queue란">Queue란?</h1>
<h2 id="개념-정리">개념 정리</h2>
<p><img src="https://velog.velcdn.com/images/daily_j/post/348bca79-f598-469e-879b-f6fc78bf5b8e/image.png" alt=""></p>
<p>Queue는, 일반적으로 우리가 줄을 서는 모습을 상상하면 이해하기 쉽다. 한 쪽에서 줄을 서고 (= Enqueue), 다른 쪽에서 줄이 마무리 (= Dequeue)가 된다. 이러한 구조를 FIFO (First In First Out) 구조라고도 한다.</p>
<p>여기서 Dequeue가 발생되는 구간을 Front, Enqueue가 발생되는 구간을 Rear라고 자주 부른다. 이를 바탕으로 어떤 주요 기능들이 있는지 살펴보자.</p>
<h2 id="주요-기능">주요 기능</h2>
<p>먼저 Queue에서 주목할 점 중 하나는 바로 Queue가 Inferface의 형태로 구현되었다는 점이다. 따라서, Queue를 바로 불러오지 않고,LinkedList()를 활용하여 값을 불러올 수 있다. (즉, 다형성을 활용하겠다는 뜻이다.)</p>
<pre><code>public class myQueueStudy {
    public static void main(String args[]){
        Queue queue = new LinkedList(); // Queue가 Interface임..
        queue.add(1);
        queue.add(2);
        queue.add(3);
        queue.add(4);
        System.out.println(&quot;queue = &quot; + queue);
        System.out.println(&quot;== Poll ==&quot;);
        System.out.println(queue.poll());
        System.out.println(&quot;queue = &quot; + queue);
        System.out.println(&quot;== Peek ==&quot;);
        System.out.println(queue.peek());
        System.out.println(&quot;queue = &quot; + queue);
        System.out.println(&quot;== Else ==&quot;);
        System.out.println(queue.contains(3));
        System.out.println(queue.size());
        System.out.println(queue.isEmpty());
        queue.clear();
        System.out.println(&quot;queue = &quot; + queue);
    }
}</code></pre><p>또 주의할 점이 하나 있는데, 여기서 enqueue가 add(), dequeue가 poll()로 구현되었음에 주의하자. 특히, front 단의 값을 확인만 하는 것(즉, 삭제 X)은 peek()임에 주의하자.</p>
<h2 id="어디서-사용하는가">어디서 사용하는가?</h2>
<h3 id="예제1-find-last-card">예제1. Find Last Card</h3>
<p>여기서는 마지막 카드를 찾는 규칙을 확인하고 remove -&gt; add를 쓰는 기법에 대해 알아보자.</p>
<pre><code>    public static int findLastCard(int N){
        Queue queue = new LinkedList();
        IntStream.range(1, N + 1).forEach(x -&gt; queue.add(x));

        while (queue.size() &gt; 1){
            queue.remove(); // 하나 지우고
            int data = (int) queue.remove(); // 하나 더 꺼내서
            queue.add(data); // 맨 아래로
        }
        return (int) queue.remove();
    }</code></pre><p>front에 위치한 값을 꺼내서 지운 후, 하나 더 꺼낸 값을 add하는 장면이 중요하다. 결과적으로 하나의 값만이 삭제되는 것을 확인해보자.</p>
<pre><code>            queue.remove(); // 하나 지우고
            int data = (int) queue.remove(); // 하나 더 꺼내서
            queue.add(data); // 맨 아래로</code></pre><h3 id="예제2-josephus">예제2. Josephus</h3>
<pre><code> public static ArrayList getJosephus(int N, int k){
        Queue queue = new LinkedList();
        ArrayList result = new ArrayList();

        IntStream.range(1, N+1).forEach(x -&gt; queue.add(x));

        int cnt = 0;
        while (!queue.isEmpty()){
            int data = (int) queue.remove();
            cnt += 1;
            if (cnt % k == 0){
                result.add(data);
            } else {
                queue.add(data);
            }
        }
        return result;
    }</code></pre><p>여기서 주목할 점은 2가지.</p>
<p>1) IntStream의 활용 -&gt; 모든 값에 같은 내용을 적용할 때 사용해보자.</p>
<pre><code>IntStream.range(1, N+1).forEach(x -&gt; queue.add(x));</code></pre><p>2) k개마다 삭제 -&gt; 즉, cnt % k == 0을 기준으로 특수 동작을 수행한다는 점
    - queue를 remove한 후 -&gt; result에 저장: 즉, queue에서 값 하나 빠짐.
    - queue를 remove한 후 -&gt; queue에 저장: 즉, 한 칸씩 값이 밀림.</p>
<pre><code>        int cnt = 0;
        while (!queue.isEmpty()){
            int data = (int) queue.remove();
            cnt += 1;
            if (cnt % k == 0){
                result.add(data);
            } else {
                queue.add(data);
            }
        }</code></pre><h1 id="deque란">Deque란?</h1>
<h2 id="개념-정리-1">개념 정리</h2>
<p><img src="https://velog.velcdn.com/images/daily_j/post/c52d5232-d9c4-4133-8c7c-52e057adb237/image.png" alt=""></p>
<p>말 그대로, 여러 곳에 값을 넣을 수 있다는 뜻이다. 상황에 따라서 입/출력 위치 값을 제한할 수도 있으나 여
기서는 Front, Rear 둘 다에서 값을 넣을 수 있다고 가정하자.</p>
<h2 id="주요-기능-1">주요 기능</h2>
<p>Deque 역시 Inferface의 형태로 구현되었다는 점이다. 따라서, deque를 바로 불러오지 않고,LinkedList()를 활용하여 값을 불러올 수 있다. (즉, 다형성을 활용하겠다는 뜻이다.)</p>
<p>front에서 값을 꺼내오는 removeFirst, rear에서 값을 꺼내오면 removeLast를 사용할 수 있다.
반대로 값을 넣는 값은 addFirst, addLast를 사용한다.</p>
<p>poll()의 경우 remove()와 유사하나, 값이 비어있으면 &quot;null&quot;을 출력한다는 점에서 차이가 있다.</p>
<pre><code>public class myDequeStudy {
    public static void main(String[] args){
        Deque deque = new ArrayDeque();

        deque.addFirst(1);
        deque.addFirst(2);
        deque.addFirst(3);
        System.out.println(&quot;deque = &quot; + deque);

        deque.addLast(10);
        deque.addLast(20);
        deque.addLast(30);
        System.out.println(&quot;deque = &quot; + deque);

        // Front
        System.out.println(deque.removeFirst());
        System.out.println(deque);

        // Rear
        System.out.println(deque.removeLast());
        System.out.println(deque);

        // Poll
        System.out.println(deque.pollFirst());
        System.out.println(deque);


        System.out.println(deque.pollFirst());
        System.out.println(deque.pollFirst());
        System.out.println(deque.pollFirst());
        System.out.println(deque.pollFirst());
        System.out.println(deque);

    }
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Stack: 백준 25556번 포스택]]></title>
            <link>https://velog.io/@daily_j/Stack-%EB%B0%B1%EC%A4%80-25556%EB%B2%88-%ED%8F%AC%EC%8A%A4%ED%83%9D</link>
            <guid>https://velog.io/@daily_j/Stack-%EB%B0%B1%EC%A4%80-25556%EB%B2%88-%ED%8F%AC%EC%8A%A4%ED%83%9D</guid>
            <pubDate>Mon, 18 Dec 2023 15:53:19 GMT</pubDate>
            <description><![CDATA[<h1 id="백준-포스택-문제">백준 포스택 문제</h1>
<ul>
<li>출처: <a href="https://www.acmicpc.net/problem/25556">https://www.acmicpc.net/problem/25556</a></li>
</ul>
<p>처음에 이거 내용 이해가 조금 어려웠는데, 구현은 그에 비해 쉬웠다. 여기서는 이해에 초점을 맞춰서 설명하겠다. (아래는 본인의 언어로 재구성한 문제 내용이다.)</p>
<p>포닉스는 길이가 $N$인 순열 $A$와 네 개의 비어 있는 스택을 가지고 있다.</p>
<ul>
<li>순열을 오름차순으로 정렬하는 것이 목적</li>
</ul>
<ol>
<li>순열 $A$의 원소들을 앞 원소부터 순서대로 네 개의 스택 중 하나에 삽입한다.</li>
<li>순열  $A$의 모든 원소를 스택에 삽입했다면, 네 개의 스택에서 모든 수를 꺼낸다.</li>
<li>꺼낸 수들을 꺼낸 순서대로 오른쪽에서 왼쪽으로 나열한다. 즉, 가장 처음에 꺼낸 수가 맨 뒤, 가장 나중에 꺼낸 수가 맨 앞에 위치하게 된다.</li>
</ol>
<h2 id="stack의-어떤-성질을-이용하는가">Stack의 어떤 성질을 이용하는가?</h2>
<p>Stack은 가장 마지막 값을 꺼낼 수 있다는 특징을 가진다. 이는 &quot;가장 처음에 꺼낸 수가 맨 뒤, 가장 나중에 꺼낸 수가 맨 앞에 위치하게 된다.&quot;와 일치하는 내용으로 Stack으로 구현이 가능할 것이다. (물론 문제에서 아예 Stack을 제시하고 있다.)</p>
<h2 id="풀이">풀이</h2>
<p>즉, 위의 상황을 다시 말하면 맨 뒤에 있는 수(즉, 가장 나중에 넣은 수)가 가장 큰 수가 되어야 한다. 예를 들어, $5,4,3,2,1$ 가 있다고 하자.</p>
<ul>
<li>&quot;5&quot;은 1번째 스택에 들어간다.</li>
<li>&quot;4&quot;은 2번째 스택에 들어간다.</li>
<li>&quot;3&quot;은 3번째 스택에 들어간다.</li>
<li>&quot;2&quot;은 4번째 스택에 들어간다.</li>
<li>&quot;1&quot;은 스택은 4개뿐이라 들어갈 곳이 없다. &quot;1&quot;은 어디에 들어가도 가장 큰 수가 될 수 없다.</li>
</ul>
<p>즉 우리는 들어갈 스택이 없는 수가 발생하는 경우를 잡으면 된다.</p>
<pre><code>import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
        // 입력 1
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        int[] array = new int[num];
        Stack&lt;Integer&gt;[] stackList = new Stack[4];
        int cnt = 0;

        // 입력 2
        for (int i = 0; i &lt; num; i++) {
            array[i] = sc.nextInt();
        }

        // 포스택 생성

        for (int i = 0; i &lt; 4; i++) {
            stackList[i] = new Stack&lt;&gt;();
        }

        // 조건 처리

        for (int item: array){
            for (Stack stack: stackList){
                if (stack.isEmpty() || (int) stack.peek() &lt;= item){
                    stack.push(item);
                    cnt ++;
                    break;
                }
            }
        }

        // 출력

        if (cnt == num){
            System.out.println(&quot;YES&quot;);
        } else {
            System.out.println(&quot;NO&quot;);
        }

    }
}</code></pre><p>아직 입력이 익숙하지 않아, Scanner를 통해 단순하게 받아왔다.</p>
<h3 id="핵심1-조건-처리">핵심1. 조건 처리</h3>
<pre><code>        // 조건 처리

        for (int item: array){
            for (Stack stack: stackList){
                if (stack.isEmpty() || (int) stack.peek() &lt;= item){
                    stack.push(item);
                    cnt ++;
                    break;
                }
            }
        }</code></pre><p>for문 2번을 활용하여 순열 A에서 숫자를 하나씩 꺼내고, 이를 Stack에 하나씩 넣어보는 시도를 진행한다.</p>
<p>조건1. 스택이 비었거나
조건2. 스택의 가장 위의 값보다 숫자 값이 큰 경우</p>
<p>Stack에 해당 숫자를 넣고 cnt를 증가시켜준다.</p>
<h3 id="핵심2-출력">핵심2. 출력</h3>
<pre><code>        // 출력

        if (cnt == num){
            System.out.println(&quot;YES&quot;);
        } else {
            System.out.println(&quot;NO&quot;);
        }</code></pre><p>스택에 넣은 횟수(cnt)와 수열의 길이 (num)를 비교하여 모든 수를 Stack에 넣었다면 &quot;YES&quot;를 출력한다.</p>
<h2 id="느낀-점">느낀 점</h2>
<p>아직 입력 함수가 익숙하지 않아, 이를 일부 찾아봤다. 또한, 문제에서 쓰이는 아이디어가 다소 겹치는듯 보이는데 이에 대한 유형화 / 아이디어 정리를 같이 하면 좋을 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Stack 정리]]></title>
            <link>https://velog.io/@daily_j/Stack-%EC%A0%95%EB%A6%AC-1</link>
            <guid>https://velog.io/@daily_j/Stack-%EC%A0%95%EB%A6%AC-1</guid>
            <pubDate>Mon, 18 Dec 2023 15:38:32 GMT</pubDate>
            <description><![CDATA[<h1 id="stack이란">Stack이란?</h1>
<h2 id="개념-정리">개념 정리</h2>
<p>Stack은, 가장 대표적으로 순서가 보존되는 데이터 구조로, 아래와 같은 그림으로 직관적으로 표기될 수 있다.
<img src="https://velog.velcdn.com/images/daily_j/post/40346cc9-a4e0-4acf-9066-992f488a519a/image.png" alt=""></p>
<p>그림에서 표현되듯이, 가장 나중에 들어온 데이터가 가장 먼저 나가게 되며 이를 LIFO (Last in Frist Out)이라고도 부른다.</p>
<h2 id="주요-기능">주요 기능</h2>
<p>가장 윗단을 가리키는 커서를 top이라고 부르며 값을 넣는 행위를 push(), top의 값을 꺼내는 행위를 pop(), top의 값을 확인하는 행위를 peek()으로 표현한다. Java에서는 java.util.Stack을 통해 표현되며 함수를 사용하는 방법도 위의 함수명과 동일하다.</p>
<pre><code>public class myStackStudy {
    public static void main(String args[]){
        Stack stack = new Stack();
        System.out.println(&quot;== Push ==&quot;);
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        System.out.println(&quot;stack = &quot; + stack);
        System.out.println(&quot;== Pop ==&quot;);
        System.out.println(stack.pop());
        System.out.println(&quot;stack = &quot; + stack);
        System.out.println(&quot;== Peek ==&quot;);
        System.out.println(stack.peek());
        System.out.println(&quot;stack = &quot; + stack);
        System.out.println(&quot;== Contains ==&quot;);
        System.out.println(stack.contains(1));
        System.out.println(&quot;== Size ==&quot;);
        System.out.println(stack.size());
        System.out.println(&quot;== Clear ==&quot;);
        stack.clear();
        System.out.println(stack.size());

    }
}</code></pre><h2 id="어디서-사용하는가">어디서 사용하는가?</h2>
<p>Stack은 주로 최근 값의 데이터를 꺼내 쓸 때 사용하며, 컴퓨터의 &quot;실행 취소&quot;를 생각하면 이해하기 쉬울 것 같다.</p>
<h3 id="예1-reversestring">예1. reverseString()</h3>
<pre><code>    public static String reverseString(String str){
        Stack stack = new Stack();
        String result = &quot;&quot;;

        for (String s: str.split(&quot;&quot;)){
            stack.push(s);
        }

        while (!stack.isEmpty()){
            result = result + stack.pop();
        }
        return result;
    }</code></pre><p>String을 반대로 뒤집는 함수로, 끝 값부터 꺼내온다는 점에서 Stack이 적합하다.</p>
<h4 id="tip-문자열---잘라서-저장하는-법">TIP) 문자열 -&gt; 잘라서 저장하는 법</h4>
<pre><code>        // 방법1. split() 활용
        for (String s: str.split(&quot;&quot;)){
            stack.push(s);
        }

        // 방법2. toCharArray() 활용
        for (char c: str.toCharArray()){
            stack.push(c);
        }</code></pre><h2 id="예2-전위--중위--후위-표기식">예2. 전위 / 중위 / 후위 표기식</h2>
<pre><code>public static double calculate(String string){
        Stack&lt;Double&gt; stack = new Stack();
        for (String s: string.split(&quot; &quot;)){
            if (s.equals((&quot;+&quot;))){
                stack.push(stack.pop() + stack.pop());
            } else if (s.equals(&quot;-&quot;)){
                stack.push(- stack.pop() + stack.pop());
            } else if (s.equals(&quot;*&quot;)){
                stack.push( stack.pop() * stack.pop());
            } else if (s.equals(&quot;/&quot;)){
                stack.push( 1/stack.pop() * stack.pop());
            } else {
                stack.push(Double.parseDouble(s));
            }
        }
        return stack.pop();
    }</code></pre><p>전위, 중위, 후위 표기식의 예시로, 연산을 만나면 2개의 값을 pop()하고, 그 외에는 push()를 하는 방법에 주목하자.</p>
]]></description>
        </item>
    </channel>
</rss>