<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>clould_container.log</title>
        <link>https://velog.io/</link>
        <description>Man in the middle</description>
        <lastBuildDate>Sat, 10 Apr 2021 05:08:08 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>clould_container.log</title>
            <url>https://images.velog.io/images/clould_container/profile/f80a3199-64a8-4e42-bcea-35518f31ceb0/social.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. clould_container.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/clould_container" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[15. 3Sum]]></title>
            <link>https://velog.io/@clould_container/15.-3Sum</link>
            <guid>https://velog.io/@clould_container/15.-3Sum</guid>
            <pubDate>Sat, 10 Apr 2021 05:08:08 GMT</pubDate>
            <description><![CDATA[<h1 id="문제">문제</h1>
<p>주어진 정수 배열 <strong>nums</strong>안에서 더해서 0이되는 서로 다른 위치에 있는 세 수들을 반환하시오.</p>
<p>Example 1:</p>
<blockquote>
<p>Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]</p>
</blockquote>
<p>Example 2:</p>
<blockquote>
<p>Input: nums = []
Output: []</p>
</blockquote>
<p>Example 3:</p>
<blockquote>
<p>Input: nums = [0]
Output: []</p>
</blockquote>
<hr>
<h1 id="풀이">풀이</h1>
<p>이번 문제는 <strong>Two-Pointer</strong>방식을 이용하면 생각보다 쉽게 풀 수 있다. 일단 <strong>Brute-Force</strong>방식을 생각해 볼 수 있지만, 역시나 시간 초과가 난다.</p>
<p>따라서, 먼저 배열을 정렬한 다음, for문을 통해 더해서 0이 될 첫번째 원소를 탐색하면서, 첫 번째 원소 이후의 원소들 중에서 두번째 원소와 세 번째 원소를 찾으면 된다.</p>
<p>여기서 한가지 생각해야 할 것은, 첫번째 보기에서도 나와있듯이, 중복되는 값들이 여러개 제시 될 수 있다. 따라서 첫 번째, 두 번째, 세 번째 원소를 정할 때, 모두 중복을 건너뛰는 코드를 넣어주어야 한다. </p>
<p>또한 놓칠수도 있는 것이, 첫번째 원소와 더해서 0이되는 두 번째, 세 번째 원소의 집합이 2개 이상일 수 도 있다는 것이다. 이러한 것을 생각한다면, 이 문제는 쉽게 해결할 수 있다.</p>
<p>이를 Python으로 구현하면 다음과 같다.</p>
<h2 id=""></h2>
<pre><code class="language-python">class Solution:
    def threeSum(self, nums: List[int]) -&gt; List[List[int]]:
        answer = []

        # nums배열 오름차순으로 정렬.
        nums.sort()

        for fst in range(len(nums) - 2):

            # nums에서 중복된 값을 제외하여 fst의 위치를 결정.
            if fst &gt; 0 and nums[fst] == nums[fst - 1]:
                continue

            # sec, trd의 위치를 결정.
            sec, trd = fst + 1, len(nums) - 1

            # 더해서 0이 되는 세 수의 위치를 탐색.
            while sec &lt; trd:
                tot = nums[fst] + nums[sec] + nums[trd]

                if tot &lt; 0:
                    sec += 1

                elif tot &gt; 0:
                    trd -= 1

                else:
                    answer.append([nums[fst], nums[sec], nums[trd]])

                    # fst위치에 있는 수와 더해서 0이되는 중복되지 않는 또 다른 sec, trd의 위치 결정.
                    while sec &lt; trd and nums[sec] == nums[sec + 1]:
                        sec += 1

                    while sec &lt; trd and nums[trd] == nums[trd - 1]:
                        trd -= 1

                    # 이전과 중복된 값에서 벗어나기 위해 sec, trd값을 한번 더 조졍.
                    sec += 1
                    trd -= 1

        return answer
</code></pre>
<p>for문 안에 while문이 있고 while문이 하나 더 중첩되어 복잡해 보일 수 있으나, fst와 더해서 0이되는 (sec, trd)가 여러 개일 수 있다는 것만 생각하면 그렇게 어렵지 않을 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[42. Trapping Rain Water]]></title>
            <link>https://velog.io/@clould_container/42.-Trapping-Rain-Water</link>
            <guid>https://velog.io/@clould_container/42.-Trapping-Rain-Water</guid>
            <pubDate>Fri, 09 Apr 2021 16:00:16 GMT</pubDate>
            <description><![CDATA[<h1 id="문제">문제</h1>
<p>너비가 1인 기둥들의 양의 정수인 높이들이 주어질 때, 비가 온 후 기둥들 사이에 담길 물의 양을 계산하시오.</p>
<p>Example 1:</p>
<blockquote>
<p>Input: height = [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6</p>
</blockquote>
<p>Example 2:</p>
<blockquote>
<p>Input: height = [4,2,0,3,2,5]
Output: 9</p>
</blockquote>
<hr>
<h1 id="풀이">풀이</h1>
<p>많이 어려웠고, 도저히 생각이 안나서 책을 참고했다. 
두 가지 풀이에 대해 이해한 것을 바탕으로 설명해 보도록 하겠다</p>
<h2 id="1-two-pointer를-이용한-풀이">1. Two-Pointer를 이용한 풀이.</h2>
<p><img src="https://images.velog.io/images/clould_container/post/dd5845f5-0872-4fd5-b64d-818c1fce97d2/KakaoTalk_20210409_230824951.jpg" alt="">
이 문제를 풀기 위해서는 아래와 같은 변수들이 필요하다.</p>
<blockquote>
<ul>
<li>left: 왼쪽에서부터 움직이고 있는 변수.</li>
</ul>
</blockquote>
<ul>
<li>right: 오른쪽에서부터 움직이고 있는 변수.</li>
<li>max_height.left: left가 지나오면서 가장 높인 기둥의 높이.</li>
<li>max_height.right: right가 지나가면서 가장 높은 기둥의 높이. </li>
</ul>
<p>이 문제는 코드를 보면서 설명하는 것이 이해가 더 잘 갈 것이다.</p>
<pre><code class="language-python">from collections import namedtuple

class Solution:
    def trap(self, height: List[int]) -&gt; int:

        #예외 처리
        if not height:
            return 0

        #변수 초기화
        volume = 0
        left, right = 0, len(height) - 1
        max_height = namedtuple(&#39;max_height&#39;, &#39;left right&#39;)
        max_height.left, max_height.right = height[left], height[right]

        #가장 높은 기둥에 도달할 때까지 while문을 반복.
        while left &lt; right:

            #왼쪽과 오른쪽의 최고 높이 갱신
            max_height.left = max(max_height.left, height[left])
            max_height.right = max(max_height.right, height[right])

            #한 번에 한 쪽씩만 움직이면서 물 더하기.
            if max_height.left &lt;= max_height.right:
                volume += max_height.left - height[left]
                left += 1
            else:
                volume += max_height.right - height[right]
                right -= 1

        return volume</code></pre>
<p>일단, 핵심은 while문 안이다. while문의 종료 조건은 left == right이다.
즉, 반복문의 매 회마다 max_height.left와 max_height.right의 값을 갱신한 후,
두 값을 비교하여 한쪽만 volume을 계산해 나간다. </p>
<p>이렇게 하면, max_height.left와 max_height.right중 어느 한 쪽이라도 낮은 쪽의 빗물은 volume에 더해지면서 이동할 것이므로, 결국 두 포인터 모두 <strong>기둥 중 가장 높은 기둥</strong>에서 만나게 된다. </p>
<h2 id="2-stack을-이용한-풀이">2. Stack을 이용한 풀이.</h2>
<p><img src="https://images.velog.io/images/clould_container/post/dda80568-2efb-4ade-a8fe-a538387a4f95/KakaoTalk_20210410_005615605.jpg" alt="">
이번엔 Stack을 이용한 풀이이다. 이번 풀이는 하나의 포인터만 사용한다.</p>
<pre><code class="language-python">class Solution:
    def trap(self, height: List[int]) -&gt; int:
        idx_stack = []
        volume = 0

        # 한 방향으로 진행한다.
        for cur_idx in range(len(height)):

            # stack이 비어있지 않고, 현재의 기둥 높이가 이전 기둥의 높이보다 높은 경우.
            while idx_stack and height[cur_idx] &gt; height[idx_stack[-1]]:
                hole_idx = idx_stack.pop()

                if not idx_stack:
                    break

                dist = cur_idx - idx_stack[-1] - 1
                waters = min(height[cur_idx], height[idx_stack[-1]]) - height[hole_idx]

                volume += dist * waters

            idx_stack.append(cur_idx)

        return volume</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[2. Two Sum]]></title>
            <link>https://velog.io/@clould_container/2.-Two-Sum</link>
            <guid>https://velog.io/@clould_container/2.-Two-Sum</guid>
            <pubDate>Fri, 09 Apr 2021 08:30:55 GMT</pubDate>
            <description><![CDATA[<h1 id="문제">문제</h1>
<p>주어진 정수 배열 <strong>nums</strong>와 정수 <strong>target</strong>에 대해, 덧셈하여 <strong>target</strong>을 만들 수 있는 배열 안의 두 수의 인덱스를 반환하여라.</p>
<p>정확히 하나의 답이 존재하며, 같은 원소를 두 번 사용하지 않을 수 있다.</p>
<p>Example 1:</p>
<blockquote>
<p>Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Output: Because nums[0] + nums[1] == 9, we return [0, 1].</p>
</blockquote>
<p>Example 2:</p>
<blockquote>
<p>Input: nums = [3,2,4], target = 6
Output: [1,2]</p>
</blockquote>
<p>Example 3:</p>
<blockquote>
<p>Input: nums = [3,3], target = 6
Output: [0,1]</p>
</blockquote>
<hr>
<h1 id="풀이">풀이</h1>
<p>당연히 생각해 볼 수 있는 풀이 방법은 <strong>brute-force</strong>이다. 하지만 이 방식으로는 시간 초과가 발생한다. </p>
<p>문제에서 분명히 하나의 답이 존재한다고 했으므로, 우리는 <strong>현재 숫자에 대한 나머지 후보가 될 수 있는 dictionary</strong>를 이용하여, 값을 찾아낼 수 있다.</p>
<p>이를 Python으로 구현하면 다음과 같다.</p>
<h2 id=""></h2>
<pre><code class="language-python">class Solution:
    def twoSum(self, nums: List[int], target: int) -&gt; List[int]:
        nums_dict = {}

        for idx, num in enumerate(nums):

            #현재 숫자 num에 대한 나머지 계산
            complement = target - num

            # 나머지가 dictionary안에 있을 경우.
            if complement in nums_dict:
                return [idx, nums_dict[complement]]

            #현재의 숫자를 key로 index를 value로 설정(현재의 값은 미래의 나머지가 될 것이므로).
            nums_dict[num] = idx</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[5. Longest Palindrome Substring]]></title>
            <link>https://velog.io/@clould_container/5.-Longest-Palindrome-Substring</link>
            <guid>https://velog.io/@clould_container/5.-Longest-Palindrome-Substring</guid>
            <pubDate>Fri, 09 Apr 2021 07:36:31 GMT</pubDate>
            <description><![CDATA[<h1 id="문제">문제</h1>
<p>문자열 <strong>s</strong>가 주어질 때, <strong>s</strong>안에서 가장 긴 팰린드롬 부분 문자열을 반환하여라.</p>
<p>Example 1:</p>
<blockquote>
<p>Input: s = &quot;babad&quot;
Output: &quot;bab&quot;
Note: &quot;aba&quot; is also a valid answer</p>
</blockquote>
<p>Example 2:</p>
<blockquote>
<p>Input: s = &quot;cbbd&quot;
Output: &quot;bb&quot;</p>
</blockquote>
<p>Example 3:</p>
<blockquote>
<p>Input: s = &quot;a&quot;
Output: &quot;a&quot;</p>
</blockquote>
<hr>
<h1 id="풀이">풀이</h1>
<p>꽤 애먹었던 문제다. 일단 Palindrome은 <strong>짝수 길이의 palindrome</strong>와 <strong>홀수 길이의 palindrome</strong>이 존재한다. 언뜻 보면 두 종류의 palindrome을 구하는 함수를 따로 구현해야 할 것 같지만, <strong>초기 왼쪽과 오른쪽을 가리키는 포인터의 간격을 조정</strong>함으로써 하나의 함수로 구할 수 있다.</p>
<p>1) <strong>Two-Pointer방식을 이용한 find_palindrome함수 구현</strong>
구현은 생각보다 간편하다. <strong>왼쪽과 오른쪽을 가리키는 포인터가 문자열의 범위를 넘지 않으면서, 서로 가리키는 문자가 같은 동안</strong>에 계속 왼쪽과 오늘쪽을 가리키는 포인터의 값을 조정하는 함수를 구현하면 된다.</p>
<p>2) <strong>예외처리</strong>
find_palindrome함수는 길이가 2 이상인 문자열에서 동작한다. 또한, 파이썬은 문자열 반전에 매우 빠른 성능을 보여 주므로, 이 두 사항을 예외로 처리하기로 한다.</p>
<p>3)  <strong>Sliding-Window기법을 이용하여 최대값 구하기.</strong> 
  이제 문자열의 문자들을 순회하며, find_palindrome이 반환하는 palindrome중 문자열의 길이가 가장 긴 문자열을 찾는다.</p>
<p>이를 Python으로 구현하면 다음과 같다.</p>
<h2 id=""></h2>
<pre><code class="language-python">class Solution:
    def longestPalindrome(self, s: str) -&gt; str:

        # 팰린드롬을 찾는 함수 구현
        def find_palindrome(left: int, right: int) -&gt; str:
            while left &gt; -1 and right &lt; len(s) and s[left] == s[right]:
                left -= 1; right += 1

            return s[left + 1: right]

        # 예외 처리
        if len(s) &lt; 2 or s == s[::-1]:
            return s

        answer = &#39;&#39;

        # 슬라이딩 윈도우의 크기 비교
        for idx in range(len(s) - 1):
            answer = max(answer, find_palindrome(idx, idx + 1), find_palindrome(idx, idx + 2), key=len)

        return answer
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[49. Group Anagrams]]></title>
            <link>https://velog.io/@clould_container/49.-Group-Anagrams</link>
            <guid>https://velog.io/@clould_container/49.-Group-Anagrams</guid>
            <pubDate>Fri, 09 Apr 2021 05:50:47 GMT</pubDate>
            <description><![CDATA[<h1 id="문제">문제</h1>
<p>주어진 문자열 배열 <strong>strs</strong>을 <a href="https://ko.wikipedia.org/wiki/%EC%96%B4%EA%B5%AC%EC%A0%84%EC%B2%A0"><strong>애너그램</strong></a>별로 그룹화하라. </p>
<p>Example 1:</p>
<blockquote>
<p>Input: strs = [&quot;eat&quot;,&quot;tea&quot;,&quot;tan&quot;,&quot;ate&quot;,&quot;nat&quot;,&quot;bat&quot;]
Output: [[&quot;bat&quot;],[&quot;nat&quot;,&quot;tan&quot;],[&quot;ate&quot;,&quot;eat&quot;,&quot;tea&quot;]]</p>
</blockquote>
<p>Example 2:</p>
<blockquote>
<p>Input: strs = [&quot;&quot;]
Output: [[&quot;&quot;]]</p>
</blockquote>
<p>Example 3:</p>
<blockquote>
<p>Input: strs = [&quot;a&quot;]
Output: [[&quot;a&quot;]]</p>
</blockquote>
<hr>
<h1 id="풀이">풀이</h1>
<p>&#39;eat&#39;와 &#39;ate&#39;는 애너그램이다. 같은 문자들로 이루어져 있기 때문에, 단어를 이루는 문자들을 <strong>사전 순서대로 정렬</strong>하게 되면, 같은 결과가 나오게 된다. 따라서 이 문제는 <strong>단어를 이루는 문자들을 사전 순서 대로 정렬 한 후, 정렬 순서대로 이어 붙인 단어</strong>를 key로 하고, 같은 값을 가지는 단어들의 list를 value로 하는 dictionary를 이용하면 쉽게 풀 수 있다.</p>
<h2 id=""></h2>
<pre><code class="language-python">from collections import defaultdict

class Solution:
    def groupAnagrams(self, strs: List[str]) -&gt; List[List[str]]:
        str_dict = defaultdict(list)

        for word in strs:
            str_dict[&#39;&#39;.join(sorted(word))].append(word)

        return str_dict.values()
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[819. Most Common Words]]></title>
            <link>https://velog.io/@clould_container/819.-Most-Common-Words</link>
            <guid>https://velog.io/@clould_container/819.-Most-Common-Words</guid>
            <pubDate>Fri, 09 Apr 2021 03:55:18 GMT</pubDate>
            <description><![CDATA[<h1 id="문제">문제</h1>
<p>문자열 <strong>paragraph</strong>와 금지된 단어들의 배열 ** banned** 가 주어진다. <strong>banned</strong>에 포함되지 않은 단어 중, 가장 많이 사용된 단어를 반환하시오. 답은 유일하며, paragraph에는 banned에 포함되지 않은 적어도 하나의 단어가 존재하고 있다.</p>
<p>Example 1:</p>
<blockquote>
<p>Input: paragraph = &quot;Bob hit a ball, the hit BALL flew far after it was hit.&quot;, banned = [&quot;hit&quot;]
Output: &quot;ball&quot;
Explanation: 
&quot;hit&quot; occurs 3 times, but it is a banned word.
&quot;ball&quot; occurs twice (and no other word does), so it is the most frequent non-banned word in the paragraph. 
Note that words in the paragraph are not case sensitive,
that punctuation is ignored (even if adjacent to words, such as &quot;ball,&quot;), 
and that &quot;hit&quot; isn&#39;t the answer even though it occurs more because it is banned.</p>
</blockquote>
<p>Example 2:</p>
<blockquote>
<p>Input: paragraph = &quot;a.&quot;, banned = []
Output: &quot;a&quot;</p>
</blockquote>
<hr>
<h1 id="풀이">풀이</h1>
<p>문제의 핵심은 <strong>banned에 포함되지 않은 단어들의 갯수를 세는 방법</strong>이다.</p>
<p>Python에서는 dictionary의 한 종류인 Counter와  defaultdict를 제공하고 있으니, 이를 이용하면 쉽게 풀이할 수 있다.</p>
<p>하지만 여기서 조심할 것은 &#39;<strong>Non-alphanumeric</strong>문자를 어떻게 걸러낼 것인가&#39; 이다. 여기서는 paragraph의 모든 문자열을 순회하며, Non-alphanumeric문자를 &#39; &#39;로 대치하는 방법을 사용할 것이다.</p>
<p>이를 Python으로 구현하면 다음과 같다.</p>
<h2 id="1-counter를-이용한-풀이">1. Counter를 이용한 풀이.</h2>
<pre><code class="language-python">from collections import Counter

class Solution:
    def mostCommonWord(self, paragraph: str, banned: List[str]) -&gt; str:
        word_list = []

        # Non-alphanumeric문자를 &#39; &#39;로 대치
        for char in paragraph:
            if not char.isalnum():
                paragraph = paragraph.replace(char, &#39; &#39;)

    # paragraph의 모든 문자들을 소문자로 변환.
        paragraph = paragraph.lower()

    #banned에 포함되지 않은 단어들을 list에 삽입.
        for word in paragraph.split():
            if word not in banned:
                word_list.append(word)

        # list를 Counter로 변환.
        word_counter = Counter(word_list)

    #가장 많이 사용된 단어 반환.
        return word_counter.most_common(1)[0][0]
</code></pre>
<h2 id="2-defaultdict를-이용한-풀이">2. defaultdict를 이용한 풀이.</h2>
<pre><code class="language-python">from collections import defaultdict

class Solution:
    def mostCommonWord(self, paragraph: str, banned: List[str]) -&gt; str:
        word_dict = defaultdict(int)

        # Non-alphanumeric문자를 &#39; &#39;로 대치
        for char in paragraph:
            if not char.isalnum():
                paragraph = paragraph.replace(char, &#39; &#39;)

    # paragraph의 모든 문자들을 소문자로 변환.
        paragraph = paragraph.lower()

    # banned에 포함되지 않은 문자를 key로 개수를 value로 하는 defaultdict 생성.
        for word in paragraph.split():
            if word not in banned:
                word_dict[word] += 1

    # defaultdict를 정렬하여 가장 많이 사용된 단어를 반환.
        return sorted(word_dict.items(), key=lambda x: x[1], reverse=True)[0][0]
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[937. Reorder Log Files]]></title>
            <link>https://velog.io/@clould_container/937.-Reorder-Log-Files</link>
            <guid>https://velog.io/@clould_container/937.-Reorder-Log-Files</guid>
            <pubDate>Fri, 09 Apr 2021 03:07:33 GMT</pubDate>
            <description><![CDATA[<h1 id="문제">문제</h1>
<p>logs배열이 주어진다. 각 log는 공백으로 구분된 단어의 문자열이며, 첫 번째 단어는 식별자이다.</p>
<p>두가지 형식의 log들이 존재한다:</p>
<ul>
<li><p><strong>Letter-logs</strong>: 식별자를 제외한 모든 단어들이 소문자로 구성된 log.</p>
</li>
<li><p><strong>Digit-logs</strong>: 식별자를 제외한 모든 단어들이 숫자로 구성된 log.</p>
</li>
</ul>
<p>다음 기준에 맞추어 로그를 재정렬하시오.</p>
<blockquote>
<ol>
<li><strong>letter-logs</strong>는 모든 <strong>digit-logs</strong>보다 앞에 온다.<ol start="2">
<li><strong>letter-logs</strong>는 <strong>사전 순서</strong>대로 정렬한다. 식별자를 제외한 모든 내용이 일치할 경우, 식별자의 사전 순서대로 정렬한다.</li>
<li><strong>digit-logs</strong>는 <strong>입력 순서를 유지</strong>한다.</li>
</ol>
</li>
</ol>
</blockquote>
<p>logs의 정렬 결과를 반환하시오.</p>
<p>Example 1:</p>
<blockquote>
<p>Input: logs = [&quot;dig1 8 1 5 1&quot;,&quot;let1 art can&quot;,&quot;dig2 3 6&quot;,&quot;let2 own kit dig&quot;,&quot;let3 art zero&quot;]
Output: [&quot;let1 art can&quot;,&quot;let3 art zero&quot;,&quot;let2 own kit dig&quot;,&quot;dig1 8 1 5 1&quot;,&quot;dig2 3 6&quot;]
Explanation:
The letter-log contents are all different, so their ordering is &quot;art can&quot;, &quot;art zero&quot;, &quot;own kit dig&quot;.
The digit-logs have a relative order of &quot;dig1 8 1 5 1&quot;, &quot;dig2 3 6&quot;.</p>
</blockquote>
<p>Example 2:</p>
<blockquote>
<p>Input: logs = [&quot;a1 9 2 3 1&quot;,&quot;g1 act car&quot;,&quot;zo4 4 7&quot;,&quot;ab1 off key dog&quot;,&quot;a8 act zoo&quot;]
Output: [&quot;g1 act car&quot;,&quot;a8 act zoo&quot;,&quot;ab1 off key dog&quot;,&quot;a1 9 2 3 1&quot;,&quot;zo4 4 7&quot;]</p>
</blockquote>
<hr>
<h1 id="풀이">풀이</h1>
<p>풀이의 골자는 다음과 같다.
&nbsp;&nbsp;#1. <strong>letter-logs</strong>와 <strong>digit-logs</strong>를 분리한다.
&nbsp;&nbsp;&nbsp;&nbsp;=&gt;여기서 <strong>digit-logs</strong>는 <strong>입력 순서를 유지</strong>하므로, 더이상 정렬할 필요가 없다.
&nbsp;&nbsp;#2. <strong>letter-logs</strong>를 정렬한다.
&nbsp;&nbsp;&nbsp;&nbsp;=&gt; 식별자를 제외한 부분을 1차 정렬 기준으로 세우고, 식별자를 2차 정렬 기준으로 세운다.
&nbsp;&nbsp;#3. 정렬한 <strong>letter-logs</strong>에 <strong>digit-logs</strong>를 이어 붙인 새로운 list를 반환한다.</p>
<p>이를 Python으로 구현하면 다음과 같다.</p>
<pre><code class="language-python">class Solution:
    def reorderLogFiles(self, logs: List[str]) -&gt; List[str]:
        letters, digits = [], []

        #1.문자로만 이루어진 log와 숫자가 포함된 log를 분리
        for log in logs:
            if log.split()[1].isdigit():
                digits.append(log)
            else:
                letters.append(log)

        #2. 문자로만 이루어진 log list를 정렬.
        letters.sort(key= lambda x: (x.split()[1:], x.split()[0]))

        #3. 문자로만 이루어진 log list와 숫자가 포함된 log list를 합침.
        return letters + digits</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[344. Reverse String]]></title>
            <link>https://velog.io/@clould_container/344.-Reverse-String</link>
            <guid>https://velog.io/@clould_container/344.-Reverse-String</guid>
            <pubDate>Thu, 08 Apr 2021 17:41:49 GMT</pubDate>
            <description><![CDATA[<h1 id="문제">문제</h1>
<p>문자열을 뒤집는 함수를 작성하라. 입력 문자열은 문자열 배열 s로 주어진다.
<strong>제한 사항</strong>
다른 배열을 추가 할당하지 말고 리스트 내부를 직접 조작할 것.</p>
<p>Example 1:</p>
<blockquote>
<p>Input: s = [&quot;h&quot;,&quot;e&quot;,&quot;l&quot;,&quot;l&quot;,&quot;o&quot;]
Output: [&quot;o&quot;,&quot;l&quot;,&quot;l&quot;,&quot;e&quot;,&quot;h&quot;]</p>
</blockquote>
<p>Example 2:</p>
<blockquote>
<p>Input: s = [&quot;H&quot;,&quot;a&quot;,&quot;n&quot;,&quot;n&quot;,&quot;a&quot;,&quot;h&quot;]
Output: [&quot;h&quot;,&quot;a&quot;,&quot;n&quot;,&quot;n&quot;,&quot;a&quot;,&quot;H&quot;]</p>
</blockquote>
<hr>
<h1 id="풀이">풀이</h1>
<h2 id="1-two-pointer방식">1. Two Pointer방식.</h2>
<p>이 풀이에서는 <strong>Two Pointer</strong>방식을 사용하여 풀이할 것이다.</p>
<pre><code class="language-python">class Solution:
    def reverseString(self, s: List[str]) -&gt; None:
        left, right = 0, len(s) - 1

        #Pointer들의 위치를 조정하며, 값을 교환한다.
        while left &lt; right:
            s[left], s[right] = s[right], s[left]
            left += 1;right -= 1</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[125. Valid Palindrome]]></title>
            <link>https://velog.io/@clould_container/125.-Valid-Palindrome</link>
            <guid>https://velog.io/@clould_container/125.-Valid-Palindrome</guid>
            <pubDate>Thu, 08 Apr 2021 17:22:43 GMT</pubDate>
            <description><![CDATA[<h1 id="문제">문제</h1>
<p>문자열 s가 주어졌을때, 이 문자열이 <a href="https://ko.wikipedia.org/wiki/%ED%9A%8C%EB%AC%B8">palindrome</a>인지 판별하시요. <a href="https://ko.wikipedia.org/wiki/%EC%98%81%EC%88%AB%EC%9E%90">alphanumeric</a> character에 대해서만 고려한다.</p>
<p>Example 1:</p>
<blockquote>
<p>Input: s = &quot;A man, a plan, a canal: Panama&quot;
Output: true
Explanation: &quot;amanaplanacanalpanama&quot; is a palindrome.</p>
</blockquote>
<p>Example 2:</p>
<blockquote>
<p>Input: s = &quot;race a car&quot;
Output: false
Explanation: &quot;raceacar&quot; is not a palindrome.</p>
</blockquote>
<hr>
<h1 id="풀이">풀이</h1>
<p>문제 풀이의 공통된 방법으로는 <strong>&#39;alphanumeric 문자들을 따로 모아야 한다는 것.&#39;</strong>이다.</p>
<h2 id="1-자료-구조를-이용한-풀이">1. 자료 구조를 이용한 풀이.</h2>
<p>이 풀이에서는 <strong>deque</strong>를 이용하여 deque의 맨 앞의 문자와, 맨 뒤의 문자를 길이가 2 이상인 동안에 계속 비교하면서 풀이한다.</p>
<pre><code class="language-python">from collections import deque

class Solution:
    def isPalindrome(self, s: str) -&gt; bool:
        deque = deque()

        # Alphanumeric을 lowercase로 변환하여 deque에 삽입한다.
        for char in s:
            if char.isalnum():
                deque.append(char.lower())

        # deque의 길이가 2 이상일 때, pop()과 popleft()의 크기를 비교한다.
        while len(deque) &gt; 1:
            if deque.pop() != deque.popleft()
                return False    # palindrome이 아니므로 False를 반환하며 종료한다.

        return True        #palindrome이므로 True를 반환하며 종료한다.</code></pre>
<h2 id="2-문자열-slicing을-이용한-풀이">2. 문자열 Slicing을 이용한 풀이.</h2>
<pre><code class="language-python">class Solution:
    def isPalindrome(self, s: str) -&gt; bool:
        p_str: str = &#39;&#39;

        # Alphanumeric을 lowercase로 변환하여 deque에 삽입한다.
        for char in s:
            if char.isalnum():
                p_str += char.lower()

        # 문자열과 뒤집은 문자열이 같은지 비교한 결과를 반환한다.       
        return p_str == p_str[::-1]</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[#4. RAID와 LVM(이론) - 1]]></title>
            <link>https://velog.io/@clould_container/4.-RAID%EC%99%80-LVM%EC%9D%B4%EB%A1%A0-1</link>
            <guid>https://velog.io/@clould_container/4.-RAID%EC%99%80-LVM%EC%9D%B4%EB%A1%A0-1</guid>
            <pubDate>Fri, 02 Apr 2021 05:51:16 GMT</pubDate>
            <description><![CDATA[<h1 id="1-raid">#1. RAID</h1>
<p><strong>RAID</strong>(<strong>R</strong>edundant <strong>A</strong>rray of [<strong>I</strong>ndependent | <strong>I</strong>nexpensive] <strong>D</strong>isks)</p>
<ul>
<li><strong>여러개의 하드 디스크</strong>에 <strong>동일한 데이터</strong>를 <strong>다른 위치에 중복해서 저장</strong>하는 방법.</li>
<li><strong>입출력의 균형</strong>을 통해 <strong>전체적인 성능을 향상</strong>시킨다.</li>
<li>운영체제는 RAID를 <strong>하나의 디스크</strong>로 인식한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[#3. Linux 활용 분야.]]></title>
            <link>https://velog.io/@clould_container/Linux-%ED%99%9C%EC%9A%A9-%EB%B6%84%EC%95%BC</link>
            <guid>https://velog.io/@clould_container/Linux-%ED%99%9C%EC%9A%A9-%EB%B6%84%EC%95%BC</guid>
            <pubDate>Fri, 02 Apr 2021 04:52:27 GMT</pubDate>
            <description><![CDATA[<h1 id="1linux-clustering">#1.Linux Clustering</h1>
<p><strong>Clustering</strong>: 여러 대의 컴퓨터를 연결하여 하나의 컴퓨터를 사용하는 효과를 내도록 구성한 시스템.</p>
<ul>
<li><p><strong>사용 목적</strong>에 따라 <strong>고계산용 클러스터(HPC)</strong>, <strong>부하분산 클러스터(LVS)</strong>, <strong>고가용성 클러스터(HA)</strong>로 구분할 수 있다.   </p>
</li>
<li><p><strong>고계산용 클러스터(High Performace Computing Cluster)</strong><br><img src="https://images.velog.io/images/clould_container/post/1c93568d-5219-4790-99fb-1c22105ba143/wulf-topo.jpg" alt=""></p>
<ul>
<li>슈퍼 컴퓨터의 구성 방법.</li>
</ul>
</li>
<li><p><strong>부하분산 클러스터(Linux Virtual Server)</strong>
<img src="https://images.velog.io/images/clould_container/post/1ae122ff-1847-4022-bda2-f39f4f8a8b09/3.png" alt=""></p>
<ul>
<li>여러대의 물리 서버(Real Server)에 <strong>부하 분산</strong>을 위한 <strong>Load Balanceer</strong>를 연결하는 구성방식을 가짐.   </li>
</ul>
</li>
<li><p><strong>고가용성 클러스터(High Availablity Clustering)</strong>
<img src="https://images.velog.io/images/clould_container/post/3631559c-0cfc-4322-b709-7fff6e75f9ed/4.jpeg" alt=""></p>
<ul>
<li>지속적인 서비스 제공을 목적으로 하는 구성 방식.</li>
<li>LV의 문제를 해결하기 위해, 부하 분산 처리를 수행하고 있는 <strong>Primary node에 오류가 발생할 경우</strong> Secondary node가 이 업무를 수행.</li>
</ul>
</li>
</ul>
<h1 id="2cloud-computing">#2.Cloud Computing</h1>
<ul>
<li><p>사용자가 제시한 작업에 필요한 컴퓨팅 자원이 작업에 할당하여 결과를 도출하도록 하는 컴퓨팅 방식.</p>
</li>
<li><p>기존의 그리드 컴퓨팅, 분산 컴퓨팅, 서버 및 스토리지 가상화 기술을 융합한 기술.
<img src="https://images.velog.io/images/clould_container/post/7b3e6b79-0851-4bb7-a06d-a6972262bfd2/2.png" alt="">
&nbsp;&nbsp;<strong>=Cloud Computing에서 제공하는 서비스=</strong></p>
</li>
<li><p>IaaS</p>
<ul>
<li><strong>I</strong>nfrastructure <strong>a</strong>s <strong>a</strong> <strong>S</strong>ervice.</li>
<li>업무 처리에 필요한 <strong>서버, PC, 저장공간</strong>과 같은 <strong>하드웨어 자원</strong>을 빌려쓰는 형태.</li>
</ul>
</li>
<li><p>PaaS</p>
<ul>
<li><strong>P</strong>latform <strong>a</strong>s <strong>a</strong> <strong>S</strong>ervice.</li>
<li><strong>소프트웨어 개발 환경</strong>을 제공받는 형태.</li>
</ul>
</li>
<li><p>SaaS</p>
<ul>
<li><strong>S</strong>oftware <strong>a</strong>s <strong>a</strong> <strong>S</strong>ervice.</li>
<li><strong>Software자체</strong>를 클라우드 형태로 빌려쓰는 형태.   <h1 id="3-big-data">#3. Big Data</h1>
</li>
</ul>
</li>
<li><p>기존의 DBMS로 관리할 수 없는 <strong>대량의 정형/비정형 데이터</strong>에서 <strong>가치를 추출하고 결과를 분석</strong>하는 기술.</p>
</li>
<li><p><strong>사회 예측</strong>, 사회 구성원에게 <strong>맞춤 정보 제공, 분석 관리</strong>.</p>
</li>
</ul>
<p><strong>Big Data관련 기술</strong></p>
<ul>
<li>기존의 통계학 및 전산학에서 사용했던 <strong>데이터 마이닝, 기계학습 자연 언어 처리, 패턴 인식</strong>등을 사용한다.</li>
<li>비정형 데이터 분석을 위한 <strong>텍스트 마이닝, 오피니언 마이닝</strong>등이 발전하고 있음.</li>
<li><strong>Hadoop, NoSQL, R</strong>등이 이용됨</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[#2. Linux 배포판]]></title>
            <link>https://velog.io/@clould_container/Linux-%EA%B0%9C%EC%9A%94</link>
            <guid>https://velog.io/@clould_container/Linux-%EA%B0%9C%EC%9A%94</guid>
            <pubDate>Thu, 01 Apr 2021 16:28:09 GMT</pubDate>
            <description><![CDATA[<h3 id="linux-배포판">Linux 배포판</h3>
<p>운영체제의 핵심적인 부분들을 Linux Kernel과 자유 소프트웨어와 공개 프로그램을 모아서 만든 운영체제.</p>
<h3 id="linux-배포판-종류">=Linux 배포판 종류=</h3>
<p><strong>Package 관리 기법</strong>에 따라 <strong>Slackware</strong>, <strong>Debian</strong>, <strong>RedHat</strong>계열로 구분할 수 있다.</p>
<p><strong>Slackware</strong>: <strong>Upstream</strong>에서 최대한 수정되어 배포되는 형식.
&nbsp;&nbsp;사용자들이 내장 프로그램을 사용하기에는 편리하나, Package 수정이 힘듦.
&nbsp;&nbsp;e.g) SuSE, Porteus등등.</p>
<p><strong>Debian</strong>: 독자 Package관리 기법인 <strong>dpkg</strong>, <strong>apt</strong>를 사용하는 배포판.
&nbsp;&nbsp;e.g)Ubuntu, Linux Mint, Kali Linux</p>
<p><strong>RedHat</strong>: 독자 Package관리 기법인 <strong>YUM</strong>, <strong>RPM</strong>를 사용하는 배포판.
&nbsp;&nbsp;e.g)RHEL, CentOS, Fedora</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[시리즈를 시작하기 앞서]]></title>
            <link>https://velog.io/@clould_container/%EC%8B%9C%EB%A6%AC%EC%A6%88%EB%A5%BC-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%EC%95%9E%EC%84%9C</link>
            <guid>https://velog.io/@clould_container/%EC%8B%9C%EB%A6%AC%EC%A6%88%EB%A5%BC-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%EC%95%9E%EC%84%9C</guid>
            <pubDate>Thu, 01 Apr 2021 13:35:00 GMT</pubDate>
            <description><![CDATA[<p>코딩 테스트를 위해 <strong>&#39;파이썬 알고리즘 인터뷰&#39;</strong>에 수록된 <strong>LeetCode</strong>속 알고리즘 문제 풀이를 내가 문제를 해결한 방식 위주로 설명할 예정이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[#1. 운영체제의 개요]]></title>
            <link>https://velog.io/@clould_container/1.-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%EC%9D%98-%EA%B0%9C%EC%9A%94</link>
            <guid>https://velog.io/@clould_container/1.-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%EC%9D%98-%EA%B0%9C%EC%9A%94</guid>
            <pubDate>Thu, 01 Apr 2021 04:52:22 GMT</pubDate>
            <description><![CDATA[<h3 id="osoperating-system">OS(Operating System)</h3>
<p>&nbsp;컴퓨터 사용자에게 <strong>프로그램 수행 환경</strong>을 제공하는 시스템 소프트웨어로, <strong>컴퓨터 하드웨어와 사용자 간의 매개체 역할</strong>을 한다.   </p>
<h4 id="os의-범위">=OS의 범위=</h4>
<img src="https://images.velog.io/images/clould_container/post/91caae61-98c6-419f-a5c5-85358124a332/1.png">

<table>
<thead>
<tr>
<th align="left">범위</th>
<th align="left">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="left">좁은범위</td>
<td align="left"><strong>하드웨어</strong>와 <strong>애플리케이션</strong> 사이의 <strong>다리 역할</strong>을 하는 <strong>kernel</strong>.</td>
</tr>
<tr>
<td align="left">넓은 범위</td>
<td align="left"><strong>kernel</strong>, <strong>middleware</strong>, <strong>Application Interface</strong>, <strong>UI Framework</strong>를 모두 포함하는 하나의 단위.</td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[시리즈를 시작하기 앞서]]></title>
            <link>https://velog.io/@clould_container/Linux1</link>
            <guid>https://velog.io/@clould_container/Linux1</guid>
            <pubDate>Thu, 01 Apr 2021 01:26:20 GMT</pubDate>
            <description><![CDATA[<p>2020 하반기 리눅스 마스터 1급 실기 시험에 불합격하여, 2021년 상반기 실기 시험을 보려고 공부중인 내용을 정리할 것이다. 2020년에는 <strong>kernel 2.6버전의 CenoOS 6.9</strong>기반으로 시험을 봤으나, 올해부터는 <strong>systemd가 적용된 CentOS 7</strong>으로 변경되었다. 이 시리즈에서는 프로젝트나 리눅스를 사용하면서 알아두면 좋겠다 하는 내용과 리눅스 마스터 1급 실기를 준비하는데 필요한 내용을 종합적으로 다룰 예정이다.</p>
]]></description>
        </item>
    </channel>
</rss>