<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>j_zero.log</title>
        <link>https://velog.io/</link>
        <description>개발하고 만드는걸 좋아합니다</description>
        <lastBuildDate>Sun, 10 Aug 2025 07:29:48 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>j_zero.log</title>
            <url>https://velog.velcdn.com/images/j_zero/profile/0dcdae11-6e64-4f7f-a5ef-f74edd6935ec/social_profile.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. j_zero.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/j_zero" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[혼자 만들면서 공부하는 딥러닝 1-2장]]></title>
            <link>https://velog.io/@j_zero/%ED%95%A9%EC%84%B1%EA%B3%B1-%EC%8B%A0%EA%B2%BD%EB%A7%9DCNN%EC%9C%BC%EB%A1%9C-%ED%8C%A8%EC%85%98-%EC%83%81%ED%92%88-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EB%B6%84%EB%A5%98%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@j_zero/%ED%95%A9%EC%84%B1%EA%B3%B1-%EC%8B%A0%EA%B2%BD%EB%A7%9DCNN%EC%9C%BC%EB%A1%9C-%ED%8C%A8%EC%85%98-%EC%83%81%ED%92%88-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EB%B6%84%EB%A5%98%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 10 Aug 2025 07:29:48 GMT</pubDate>
            <description><![CDATA[<h2 id="용어">용어</h2>
<ul>
<li><code>LeNet</code> : 합성곱 신경망(CNN)의 초기 형태라 할 수 있는 모델. 페이스북의 얀 르쿤이 개발한 딥러닝 모델이다.</li>
<li><code>ANN</code> : Artificial neural network, 인공 신경망</li>
<li><code>CNN</code> : Convolutional neural netwokr, 합성곱 신경망</li>
<li><code>뉴런 / 유닛</code> : 인공 신경망의 기본 계산 단위. 뉴런 또는 유닛 둘 다 같은 의미.</li>
<li><code>필터 / 커널</code> : 합성곱 신경망의 기본 계산 단위. 인공 신경망의 <code>뉴런 / 유닛</code>과 같은 의미다.</li>
<li><code>입력층</code> : 처음 들어오는 데이터를 받는 곳. 신경망이 처리해야 할 원본 데이터를 전달하는 역할을 맡음.</li>
<li><code>은닉층</code> : 입력층과 출력층 사이에 있는 모든 층을 은닉층이라고 부름. 복잡한 계산을 통해 입력 데이터의 패턴을 찾고, 중요한
특징을 뽑아냄.</li>
<li><code>출력층</code> : 최종 결과를 내는 곳. 신경망의 최종 값을 만든다는 의미에서 출력층이라고 부름.</li>
<li><code>합성곱층(convolutional layer)</code> : 이미지의 작은 부분을 스캔하여 중요한 특성을 추출하는 층. 특별히 합성곱 계산을 통해 압축적으로 얻은 출력을 <strong>특성 맵</strong><sup>feature map</sup>이라고 부름.</li>
<li><code>풀링층(pooling layer)</code> : 합성곱층에서 추출한 특성 맵을 압축(축소)하는 층. 특성 맵을 축소해 처리 속도를 높이고, 모델이 더 중요한 패턴에 집중하도록 만드는 층.</li>
<li><code>밀집층(dense layer)</code> : 이전 층에서 추출된 특성을 바탕으로 최종 결과를 도출하는 층. 밀집층의 출력층에서는 추출된 이미지의 패턴을 바탕으로 분류 작업을 수행함. 
<sup>밀집층은 각각의 입력 값이 모든 뉴런에 연결되기 때문에 완전 연결층(fully connected layer)이라고도 불림.</sup></li>
<li><code>패딩(padding)</code> : 이미지의 가장자리에 빈 공간(0)을 추가해 이미지 가장자리 부분의 픽셀이 처리될 수 있도록 함. </li>
<li><code>세임 패딩(same padding)</code> : 입력과 특성 맵의 크기를 동일하게 만들기 위해 입력 주위에 적절한 개수의 패딩을 추가하는 방식.</li>
<li><code>밸리드 패딩(valid padding)</code> : 패딩 없이 순수한 입력 배열에 대해서만 합성곱을 수행해 특성 맵을 만드는 방식.</li>
<li><code>스트라이드(stride)</code> : 필터가 이미지 위를 이동하는 속도를 의미. 기본값은 1로, 예를 들면 입력 받은 이미지를 필터 크기만큼 1픽셀씩 이동하면서 스캔함. </li>
<li><code>평균 풀링(Average pooling)</code> : 풀링 윈도 내에서 평균값을 구해 출력해 냄.</li>
<li><code>최대 풀링(max pooling)</code> : 풀링 윈도 내에서 최대값을 구해 출력해 냄.</li>
</ul>
<h2 id="합성곱층convolutional-layer">합성곱층(Convolutional layer)</h2>
<pre><code class="language-python">import keras
from keras import layers
import numpy as np

# 정규 분포의 평균 : 0.0(기본값)
# 표준편차 : 1.0
# 생성하려는 배열의 크기 : (10 * 28 * 28 * 10) (w, x, y, z)
# normal() 함수를 사용해 28*28*1 크기의 흑백 이미지 10개를 랜덤으로 생성합니다. (1은 입력 데이터의 채널 수)
x = np.random.normal(size=(10, 28, 28, 1))</code></pre>
<ol>
<li>필요한 라이브러리를 로드합니다.</li>
<li>테스트에 사용할 (28, 28) 크기 흑백 이미지를 10개 랜덤하게 생성합니다.</li>
</ol>
<pre><code class="language-python">conv1 = layers.Conv2D(filters=10, kernel_size=(3, 3))

# 첫 번째 합성곱층에 x를 입력으로 전달하고 특성 맵을 출력합니다.
# 필터 개수와 커널 크기를 지정하는 합성곱층을 추가합니다.
conv_out = conv1(x)

# shape 속성을 사용해 합성곱층을 통과한 입력 데이터의 크기를 확인합니다.
# 커널 크기가 (3, 3)이고 패딩을 추가하지 않았기 때문에 높이와 너비가 2식 줄어들었고
#(valid padding으로 인한 특성 맵 축소)
print(conv_out.shape) # output : (10, 26, 26, 10)</code></pre>
<ol>
<li>Conv2D 클래스로 2차원 합성곱 레이어를 만듭니다(=conv1). <code>filters</code>는 사용할 필터의 개수, <code>kernel_size</code>는 커널의 크기입니다</li>
<li>합성곱 레이어에 입력 데이터를 넣어서 나온 특성 맵의 차원을 출력합니다.</li>
<li>결과가 (10, 26, 26, 10)으로 나왔습니다. 각각의 의미를 살펴보자면,<ul>
<li><code>10</code> : 10개의 이미지가 그대로 처리되었다. (앞서 설정한 더미 이미지 데이터 10개)</li>
<li><code>26</code> : 각 이미지의 높이가 26이다.</li>
<li><code>26</code> : 각 이미지의 너비가 26이다.</li>
<li><code>10</code> : 필터 10개를 사용했더니, <strong>깊이</strong>가 10으로 늘어났다.</li>
</ul>
</li>
</ol>
<p><img src="https://velog.velcdn.com/images/j_zero/post/666a40f0-2602-4632-b1a5-52b1a5b0d639/image.png" alt="">
필터의 개수가 10개니까 나오는 특성 맵의 개수도 10개고, 이 특성 맵을 하나의 결과로 만들면, 깊이가 10인 특성 맵 하나가 만들어집니다.</p>
<p><img src="https://velog.velcdn.com/images/j_zero/post/16582158-2882-48f4-a012-c95dd8455efa/image.gif" alt="">
높이와 너비가 26으로 줄은 이유는 커널의 크기가 (3, 3)이고, 패딩을 추가하지 않았기 때문입니다.</p>
<pre><code class="language-python">conv2 = layers.Conv2D(filters=10, kernel_size=(3, 3), strides=(2, 2))

print(conv2(x).shape) # (10, 13, 13, 10)</code></pre>
<p>스트라이드 값을 2로 주니 한 칸 씩 건너 뛰면서 합성곱을 진행해서 출력 크기가 이전보다 절반이 줄어든 모습을 볼 수 있습니다.</p>
<pre><code class="language-python"># padding 방식을 same(세임)으로 변경합니다.
conv3 = layers.Conv2D(filters=10, kernel_size=3, strides=2, padding=&#39;same&#39;)

print(conv3(x).shape) # (10, 14, 14, 10)</code></pre>
<p>스트라이드가 2이고 세임 패딩을 사용했기 때문에 (28, 28)이었던 입력의 높이와 너비 크기가 정확히 절반으로 줄어들어
(14, 14)가 되었습니다. 만약 스트라이드를 기본값으로 사용한다면 (28, 28) 크기의 특성맵으로 입력과 동일해질겁니다.</p>
<hr>
<h2 id="풀링층pooling-layer">풀링층(Pooling layer)</h2>
<pre><code class="language-python"># 풀링 윈도를 각각 (2, 2), (3, 3) 크기로 만듭니다.
pool1 = layers.AveragePooling2D(pool_size=(2, 2))
pool2 = layers.AveragePooling2D(pool_size=(3, 3))

# 만들어진 풀링 윈도로 원본 데이터를 평균 풀링합니다.
# (28, 28)크기를 (2, 2)로 절삭해 압축하니 (14, 14) 크기로 변환됐습니다.
print(pool1(x).shape) # (10, 14, 14, 1)
# (28, 28)크기를 (3, 3)로 절삭해 압축하니 (9, 9) 크기로 변환됐습니다.
print(pool2(x).shape) # (10, 9, 9, 1)</code></pre>
<p>풀링을 통해 원본<code>(28, 28)</code>을 축소(압축)하니 풀링 윈도가 <code>(2, 2)</code>일 땐 절반 크기인 (14, 14)로, <code>(3, 3)</code>일 땐 (9, 9)로 압축됐습니다. 기본적으로 풀링 윈도에 딱 맞지 않는 짜투리 부분은 버려집니다.</p>
<h2 id="밀집층dense-layer">밀집층(Dense layer)</h2>
<pre><code class="language-python"># 뉴런이 3개짜리인 밀집층을 만듭니다.
dense1 = layers.Dense(3)

# 2개짜리 입력 특성을 만듭니다.
# 2차원으로 입력값을 넘기는 이유는 케라스 층에 전달되는 입력의 첫 번째 차원은
# 항상 배치 차원, 즉 데이터 묶음이여야 하기 때문에 입력값의 크기를 (2)이 아닌 (1,2)인 2차원 배열로 만듭니다.
x2 = np.array([[5, 7]])

print(dense1(x2).shape) # (1, 3)</code></pre>
<p><img src="https://velog.velcdn.com/images/j_zero/post/32ba9cf0-635b-4841-b7ff-daf38db5cf92/image.png" alt=""></p>
<p>밀집층은 입력과 가중치의 점곱<sup>dot product</sup>을 수행합니다. 점곱 연산은 다음과 같은 수식으로 나타낼 수 있습니다.</p>
<p>$$
y = x \cdot W + b
$$</p>
<p>$$ </p>
<p>\begin{bmatrix}
    5 &amp; 7 
\end{bmatrix}</p>
<p>\cdot</p>
<p>\begin{bmatrix}
    1 &amp; 2 &amp; 3 \
    4 &amp; 5 &amp; 6 \
\end{bmatrix}</p>
<p>+</p>
<p>\begin{bmatrix}
    0 &amp; 0 &amp; 0
\end{bmatrix}</p>
<p>=</p>
<p>\begin{bmatrix}
    (5<em>1) + (7</em>4) &amp; (5<em>2) + (7</em>5) &amp; (5<em>3)+(7</em>6) \
\end{bmatrix}</p>
<p>\
= \left[\begin{matrix}33 &amp; 45 &amp; 57\end{matrix}\right]
$$</p>
<p>결과값의 형태가 (3, 1)크기로 나오는 이유는 중간에 입력값에 곱하는 가중치, 커널의 크기가 (입력 크기, 유닛 개수)이기 때문입니다. 유닛은 각각의 입력값에 대해 가중치를 가져야 하며 이 가중치가 각 유닛 마다 갖고 있어야하기 때문에 가중치, 즉 커널의 크기(입력 크기, 유닛 개수)가 (2, 3)이 됩니다.</p>
<p>```python
weight = dense1.get_weights()[0]
print(np.dot(x2, weight)) # [[33. 45. 57.]]</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[LeetCode - 204(JS, Medium)]]></title>
            <link>https://velog.io/@j_zero/LeetCode-204JS-Medium</link>
            <guid>https://velog.io/@j_zero/LeetCode-204JS-Medium</guid>
            <pubDate>Mon, 13 May 2024 14:58:47 GMT</pubDate>
            <description><![CDATA[<h1 id="leetcode---204-count-primes">LeetCode - 204. Count Primes</h1>
<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/j_zero/post/0d95371f-82b2-43b8-a747-5aab721b88bc/image.png" alt=""></p>
<h2 id="설명">설명</h2>
<p>자연수 중에서 <code>n</code>까지 소수의 개수를 반환하는 문제다.</p>
<p>전제 조건에 <code>n</code>의 값이 최대 $$5 * 10^6$$ 이므로 수 하나하나 약수가 있는지 나눠가면서 판별하면 Time Complexity가 <code>O(N^2)</code>으로 매우 높아지기에 <code>에라토스테네스의 체</code>라는 알고리즘을 사용해 문제를 해결하기로 했다.</p>
<h3 id="에라토스테네스의-체">에라토스테네스의 체</h3>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/b/b9/Sieve_of_Eratosthenes_animation.gif?20111122163028" alt=""></p>
<ol>
<li><p>에라토스테네스의 체는 가장 먼저 소수를 판별할 범위만큼 배열을 할당하여, 해당하는 값을 넣어주고, 이후에 하나씩 지워나가는 방법을 이용한다.</p>
</li>
<li><p>배열을 생성하여 초기화한다.</p>
</li>
<li><p>2부터 시작해서 특정 수의 배수에 해당하는 수를 모두 지운다.(지울 때 자기자신은 지우지 않고, 이미 지워진 수는 건너뛴다.)</p>
</li>
<li><p>2부터 시작하여 남아있는 수를 모두 출력한다.</p>
</li>
</ol>
<h2 id="풀이">풀이</h2>
<pre><code class="language-js">/**
 * @param {number} n
 * @return {number}
 */
var countPrimes = function(n) {
    // 2부터 n까지 숫자를 담을 배열
      let nums = [];
    let cnt = 0;

      // 배열에 2번 인덱스부터 n번 인덱스까지 초기값을 1로 설정(1이면 소수)
    for(let i = 2; i &lt;= n; i++){
        nums[i] = 1;
    }

       /* 
     * n의 제곱근까지만 판별하는 이유는 어떤 수의 소수의 여부를 확인 할 때는, 
     * 특정한 숫자의 제곱근 까지만 약수의 여부를 검증하면 O(N^1/2)의 시간 복잡도로 
     * 빠르게 구할 수 있다.
     */
    for(let i = 2; i &lt; Math.sqrt(n); i++){
          // 자기 자신을 제외한 배수를 소수에서 제외한다.
        for(let j = i*i; j &lt; n; j += i){
            nums[j] = 0;
        }
    }

      // 소수로 남은 숫자의 개수를 센다
    for(let i = 2; i &lt; n; i++){
        if(nums[i] === 1) ++cnt;
    }

    return cnt;
};</code></pre>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://velog.io/@max9106/Algorithm-%EC%97%90%EB%9D%BC%ED%86%A0%EC%8A%A4%ED%85%8C%EB%84%A4%EC%8A%A4%EC%9D%98-%EC%B2%B4">[Algorithm] 에라토스테네스의 체 - Junseo Kim</a></li>
<li><a href="https://ko.wikipedia.org/wiki/%EC%97%90%EB%9D%BC%ED%86%A0%EC%8A%A4%ED%85%8C%EB%84%A4%EC%8A%A4%EC%9D%98_%EC%B2%B4">에라토스테네스의 체 - 위키백과, 우리 모두의 백과사전</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[LeetCode - 98(JS, Medium)]]></title>
            <link>https://velog.io/@j_zero/LeetCode-98JS-Medium</link>
            <guid>https://velog.io/@j_zero/LeetCode-98JS-Medium</guid>
            <pubDate>Mon, 13 May 2024 14:26:10 GMT</pubDate>
            <description><![CDATA[<h1 id="leetcode---98-validate-binary-search-treebst">LeetCode - 98. Validate Binary Search Tree(BST)</h1>
<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/j_zero/post/49268eaf-0e27-4acd-82b6-b2e80dc81a75/image.png" alt="">
<img src="https://velog.velcdn.com/images/j_zero/post/0250d551-8565-4bed-9283-7f7f1e4df12c/image.png" alt=""></p>
<h2 id="설명">설명</h2>
<p>이진 트리의 <code>root</code>가 주어지고 트리가 Binary Search Tree(이하 BST)인지 검증하는 문제다.</p>
<p>BST가 되기 위해선 3가지 조건이 있는데</p>
<ul>
<li>부모 노드의 왼쪽 자식 노드는 부모 노드보다 작아야 한다.</li>
<li>부모 노드의 오른쪽 자식 노드는 부모 노드보다 커야 한다.</li>
<li>양쪽 서브 트리들은 위 두 가지 성질을 만족해야 한다.</li>
</ul>
<p>추가적으로 문제에 전제조건이 있는데</p>
<ul>
<li>트리에 있는 노드의 개수는 [$$1$$, $$10^4$$] 개다.</li>
<li>노드의 값은 [$$-2^{31}$$, $$2^{31}-1$$]이다.</li>
</ul>
<h2 id="풀이">풀이</h2>
<pre><code class="language-js">/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {boolean}
 */
var isValidBST = function(root, min = -Infinity, max = Infinity) {

    if(!root) return true;

    if(root.val &lt;= min || root.val &gt;= max) return false;

    return isValidBST(root.left, min, root.val) &amp;&amp; isValidBST(root.right, root.val, max);

};</code></pre>
<p>재귀적으로 서브 트리에 있는 자식 노드를 호출하며 중간에 부모 노드보다 큰 <code>left node</code> 혹은 작은 <code>right node</code>가 있는지 검사한다. </p>
<p>가장 밑에 있는 노드까지 검사하면서 부모 노드보다 큰 <code>left node</code> 또는 작은 <code>right node</code>가 발견되지 않을 경우 <code>true</code>를 반환하고, 발견될 경우 <code>false</code>를 반환한다.</p>
<p>이렇게 재귀적으로 검사한 값은 최종적으로 <code>root node</code>로 돌아가는데 이때 왼쪽 노드들 중에서 검사한 값이랑 오른쪽 노드들에서 검사한 값이 둘다 <code>true</code>일 경우에만 <code>true</code>를 반환하고 이외에는 <code>false</code>를 반환한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[LeetCode - 104(JS, Easy)]]></title>
            <link>https://velog.io/@j_zero/LeetCode-104JS-Easy</link>
            <guid>https://velog.io/@j_zero/LeetCode-104JS-Easy</guid>
            <pubDate>Mon, 13 May 2024 14:06:56 GMT</pubDate>
            <description><![CDATA[<h1 id="104-maximum-depth-of-binary-tree">104. Maximum Depth of Binary Tree</h1>
<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/j_zero/post/71b51541-3f9a-441b-9beb-466e99b21366/image.png" alt=""></p>
<hr>
<h2 id="설명">설명</h2>
<p>이진 트리의 루트를 받아 해당 트리의 가장 깊은 깊이(depth)를 반환하면 된다.</p>
<p>트리의 최고 깊이를 찾는 문제니까 DFS를 이용해서 문제를 풀었는데 DFS는 <code>스택 또는 재귀함수</code>로 구현할 수 있다.</p>
<p>나는 스택보단 재귀함수가 좀 더 보기 편해서 재귀함수로 구현했다.</p>
<h2 id="풀이">풀이</h2>
<pre><code class="language-js">var DFS = (node, depth) =&gt; {
    // 탐색할 노드가 없으면 lev를 반환
    if(!node) return depth;

    // 왼쪽, 오른쪽 순으로 순회하며 탐색
    let left = DFS(node.left, depth + 1);
    let right = DFS(node.right, depth + 1);

    return Math.max(left, right);
}
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var maxDepth = function(root) {
    return DFS(root, 0);
};</code></pre>
<h4 id="root-node3에서-시작">root node(3)에서 시작:</h4>
<pre><code class="language-js">if(!node) return depth</code></pre>
<ol>
<li>빈 노드가 이니기 때문에 계속 진행한다.</li>
</ol>
<pre><code class="language-js">let left = DFS(node.left , depth + 1);</code></pre>
<ol start="2">
<li>왼쪽 노드(9) 호출. </li>
</ol>
<h4 id="child-node9-호출">child node(9) 호출:</h4>
<pre><code class="language-js">if(!node) return depth</code></pre>
<ol>
<li>빈 노드가 아니니까 패스<pre><code class="language-js">let left = DFS(node.left , depth + 1);</code></pre>
</li>
<li>왼쪽 노드를 호출하지만, 빈 노드여서 현재 depth인 1 반환.<pre><code class="language-js">let right = DFS(node.right , depth + 1);</code></pre>
</li>
<li>오른쪽 노드 역시 빈 노드여서 1 반환.</li>
</ol>
<h4 id="root-node3으로-돌아가기">root node(3)으로 돌아가기:</h4>
<ol>
<li>왼쪽 노드 탐색 후 오른쪽 노트 탐색<pre><code class="language-js">let right = DFS(node.right , depth + 1);</code></pre>
</li>
</ol>
<h4 id="child-node20-호출">child node(20) 호출:</h4>
<ol>
<li>빈 노드가 아니니까 패스</li>
<li>왼쪽 노드 <code>15</code> 호출</li>
</ol>
<h4 id="child-node15-호출">child node(15) 호출:</h4>
<ol>
<li>자식 노드가 없으니 <code>depth = 2</code> 반환.</li>
</ol>
<h4 id="child-node20으로-돌아가기">child node(20)으로 돌아가기:</h4>
<ol>
<li>오른쪽 노드 <code>7</code> 호출</li>
</ol>
<h4 id="child-node7-호출">child node(7) 호출:</h4>
<ol>
<li>자식 노드가 없으니 <code>depth = 2</code> 반환.</li>
</ol>
<h4 id="child-node20으로-돌아가기-1">child node(20)으로 돌아가기:</h4>
<pre><code class="language-js">return Math.max(left, right);</code></pre>
<ol>
<li>노드 <code>20</code>의 왼쪽 노드 <code>13</code>, 오른쪽 노드 <code>7</code>의 깊이를 비교해서 더 큰 값을 반환.<h4 id="root-node3으로-돌아가기-1">root node(3)으로 돌아가기:</h4>
<pre><code class="language-js">let left = DFS(node.left, depth + 1);
let right = DFS(node.right, depth + 1);
</code></pre>
</li>
</ol>
<p>return Math.max(left, right);</p>
<pre><code>1. left는 `1`, right는 `2`이므로 둘 중 더 큰 수인 `right = 2` 를 반환.</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Leetcode - 125. Valid Palindrome (JS, Easy)]]></title>
            <link>https://velog.io/@j_zero/Leetcode-125.-Valid-Palindrome-JS-Easy</link>
            <guid>https://velog.io/@j_zero/Leetcode-125.-Valid-Palindrome-JS-Easy</guid>
            <pubDate>Mon, 06 May 2024 14:02:37 GMT</pubDate>
            <description><![CDATA[<h2 id="125-valid-palindrome">125. Valid Palindrome</h2>
<h3 id="문제">문제</h3>
<p><img src="https://velog.velcdn.com/images/j_zero/post/c7ea4704-81d0-4644-9aa0-4a50c6ff09e9/image.png" alt=""></p>
<h3 id="💬-설명">💬 설명</h3>
<blockquote>
<p>구(phrase)를 거꾸로 읽어도 제대로 읽은 것과 같은걸 회문(palindrome)이라 한다.
이 문제는 어떠한 구가 주어지면 그 구가 회문인지 아닌지를 판별하면 되는 문제다.</p>
</blockquote>
<hr>
<h3 id="📜-풀이">📜 풀이</h3>
<pre><code class="language-js">/**
 * @param {string} s
 * @return {boolean}
 */
var isPalindrome = function(s) {
    let reg = /[^a-zA-Z|0-9]/gim;
    s = s.replace(reg, &#39;&#39;).toLowerCase();

    let l = 0, r = s.length - 1;

    while(l &lt; r){
        if(s[l] !== s[r]) return false;
        l++; r--;
    }

    return true;
};</code></pre>
<blockquote>
<p>구에서 불필요한 특수문자나 공백을 지우고 모든 문자를 소문자로 바꿔서 앞뒤로 서로 같은지 판별하면 된다.
/[^a-zA-Z|0-9]/gim 는 영문, 숫자를 제외한 모든 문자를 찾는 정규식이다.</p>
</blockquote>
<hr>
<p><img src="https://velog.velcdn.com/images/j_zero/post/8061ffd3-e6a7-49de-8d25-24b91794b625/image.png" alt=""><br/></p>
<h3 id="🔎-패턴">🔎 패턴</h3>
<p>매칭하여 검색하고 싶은 문자열을 지정한다.
기존처럼 문자열의 따옴표를 포함해서 선언하면 따옴표까지도 검색하기 때문에 따옴표는 생략한다.</p>
<p>정규 표현식 패턴을 작성할 때는 일반 문자와 특수 문자를 사용할 수 있는데,
일반 문자는 리터럴 문자 / 특수 문자는 메타 문자로 표현한다.</p>
<blockquote>
<p>리터럴 문자 (정규 문자) : 일반 문자, \0, \n, \t, \v, \f, \r, \xhh, \uhhhh, \cX
메타 문자 (정규 표현식의 구문 문자) : ^ $ \ . * + ? ( ) [ ] { } |_</p>
</blockquote>
<h3 id="🔎-플래그">🔎 플래그</h3>
<p>플래그는 정규 표현식의 옵션이므로 선택적으로 사용이 가능하다.
순서와 상관없이 하나 이상의 플래그를 동시에 설정할 수 있다.
플래그를 사용하지 않는 경우에는 문자열 내 검색 대상이 1개 이상이더라도 첫번째 조건 대상만을 검색하고 종료하게 된다.</p>
<blockquote>
<p>🚩 대표적인 플래그
i (ignore case) : 대소문자를 구별하지 않고 검색한다.
g (global) : 문자열 내의 모든 패턴을 검색한다.
m (multi line) : 문자열의 행이 바뀌더라도 검색은 계속한다.</p>
</blockquote>
<h3 id="🔗-references">🔗 References</h3>
<p><a href="https://velog.io/@purplew/Javascript-%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D#%EF%B8%8F-%EB%A9%94%ED%83%80-%EB%AC%B8%EC%9E%90--%EA%B2%80%EC%83%89-%ED%8C%A8%ED%84%B4">Javascript에서 정규표현식(Regular Expression) 사용하기</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[인터넷의 작동원리]]></title>
            <link>https://velog.io/@j_zero/%EC%9D%B8%ED%84%B0%EB%84%B7%EC%9D%98-%EC%9E%91%EB%8F%99%EC%9B%90%EB%A6%AC</link>
            <guid>https://velog.io/@j_zero/%EC%9D%B8%ED%84%B0%EB%84%B7%EC%9D%98-%EC%9E%91%EB%8F%99%EC%9B%90%EB%A6%AC</guid>
            <pubDate>Tue, 23 Apr 2024 14:37:29 GMT</pubDate>
            <description><![CDATA[<h2 id="시작하기에">시작하기에</h2>
<p>인터넷이란, 컴퓨터들이 서로 통신 가능한 거대한 네트워크로</p>
<p>인터넷의 초기 형태이였던 ARPANET은 냉전 중 1969년에 미 국방부 고등연구계획국(ARPA)에서 컴퓨터가 먼 거리에서 서로 통신할 수 있는 네트워크를 구축하는 것을 목표로 ARPANET이라는 프로젝트를 시작했다.</p>
<p>군사 및 연구 목적으로 사용되었던 ARPANET이 1980년대에 임무를 완수하고 단계적으로 폐지되면서
연구 목적으로 사용되다 규모가 커지고 나서 이젠 모두가 사용하는 <strong>인터넷</strong>이 되었다.</p>
<h3 id="단순-네트워크">단순 네트워크</h3>
<h3 id="11-연결">1:1 연결</h3>
<p>기본적으로 인터넷은 컴퓨터들이 서로 물리적으로(이더넷 케이블 등) 또는 
무선으로 연결되어 두 대 이상의 컴퓨터가 데이터를 주고 받는것이다.
<img src="https://velog.velcdn.com/images/j_zero/post/be229912-9b4d-4dcd-b0c1-5fa89e4be99a/image.png" alt="" title="1:1 연결"></p>
<p>모든 현대 컴퓨터들은 이러한 연결 중 하나를 이용하여 데이터를 주고 받는다.</p>
<p>하지만 아래와 같이 인터넷은 두 대의 컴퓨터가 연결되어 있는 것이 아니라, 무수히 많은 컴퓨터가 연결되어 있는데 모든 컴퓨터끼리 연결을 하기엔 매우 복잡해진다. 예를 들어 컴퓨터 10대가 있는 네트워크를 구성하려면 $10(10-1)/2 = 45$개의 케이블이 필요하다.
<img src="https://velog.velcdn.com/images/j_zero/post/7ef755b8-7c45-498f-9973-bc682d736236/image.png" alt=""><br/></p>
<p>이러한 문제점을 해결하기 위해 우리는 <strong>라우터</strong>라는 특수한 소형 컴퓨터를 사용하는데
이 <strong>라우터</strong>라는 소형 컴퓨터는 한 가지 작업만 하게 설계되어있다.
철도역의 신호원처럼 주어진 컴퓨터에서 보낸 메시지가 올바른 대상 컴퓨터에 도착하는지 확인한다. 컴퓨터 A가 컴퓨터 B에게 메시지를 보내기 위해선 <strong>라우터에 메시지를 보내고</strong> 라우터는 받은 메시지를 <strong>수신자인 컴퓨터 B에게 전달해야한다</strong>. 또한 <strong>다른 컴퓨터로 송신되지 않게 해야한다</strong>.
<img src="https://velog.velcdn.com/images/j_zero/post/0f7b4bee-f229-4326-bdc9-538e59eff388/image.png" alt="" title="N:M 연결"><br/></p>
<p>라우터를 설치하니 모든 컴퓨터끼리 케이블을 연결했을 때와 다르게 각 컴퓨터를 라우터에 연결하면 되니 케이블을 10개만 사용해도 된다.</p>
<hr>
<h3 id="네트워크-속-네트워크">네트워크 속 네트워크</h3>
<p>라우터를 사용해 여러 대의 컴퓨터를 수용할 수 있게 됐지만, 아직 라우터 하나론 더 많은 컴퓨터를 수용하기엔 라우터의 플러그 수도 제한되어있다. 이런 문제를 해결하기 위해 라우터도 컴퓨터와 마찬가지로 라우터끼리 연결할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/j_zero/post/ea13957d-85f6-4be8-9dc5-be8157b0f8c4/image.png" alt="라우터끼리 연결" title="라우터끼리 연결"><br/></p>
<p>컴퓨터와 라우터를 연결하고 라우터와 라우터를 연결해 무한하게 네트워크를 확장할 수 있다.
<img src="https://velog.velcdn.com/images/j_zero/post/4c02e578-78d4-40d1-9454-302b979cf1c9/image.png" alt="" title="라우터로 네트워크 확장"><br/></p>
<p>이 네트워크는 우리가 인터넷이라 부르는 것과 매우 유사하다.</p>
<p>상대적으로 적은 케이블로 많은 컴퓨터를 연결이 가능하다. 하지만 아직까진 물리적인 한계가 있다.
만약 내가 아주 먼 곳까지 네트워크를 연결하고 싶은데 그곳까지 라우터와 유선 케이블을 연결하기엔 무리가 있다.</p>
<p>하지만 우리는 집집마다 전화선이라는 케이블이 설치되있다. 전화기 기반의 시설은 이미 세계 어느 곳과도 연결되어 있으므로 우리가 필요로 하는 완벽한 배선이니 전화선을 이용하면 된다.
우리는 네트워크와 전화 시설을 연결하기 위해 모뎀(MODEM, Modulator and DEModulator)이라는 특수 장비가 필요하다.</p>
<p>이 모뎀은 우리 네트워크의 정보를 전화 시설에서 처리 할 수있는 정보로 바꾸며, 그 반대의 경우도 마찬가지로 네트워크에서 처리할 수 있는 정보로 바꿔준다.
<img src="https://velog.velcdn.com/images/j_zero/post/2181c6b5-7b32-485b-a60b-cf309de4c2b8/image.png" alt=""><br/>
모뎀을 통해 우리의 네트워크는 전화 시설에 연결된다.</p>
<p>그리고 우리의 네트워크에서 도달하려는 네트워크에 메시지를 보내야 한다.</p>
<p>이 메시지가 전달되려면 인터넷 서비스 제공 업체(ISP, Internet Service Provider)에 연결되어야 한다.</p>
<p><img src="https://velog.velcdn.com/images/j_zero/post/61d7ef82-b29e-4182-9a9a-93a0f9e6721a/image.png" alt=""><br/></p>
<blockquote>
<p>ISP는 모두 함께 연결되는 몇몇 특수한 라우터를 관리하고 다른 ISP의 라우터에도 액세스 할 수 있는 회사이다. 우리나라에는 SKT, KT, LG 등이 있다.</p>
</blockquote>
<p>따라서 우리 네트워크의 메시지는 ISP 네트워크의 네트워크를 통해 대상 네트워크로 전달된다.</p>
<hr>
<h3 id="컴퓨터-찾기">컴퓨터 찾기</h3>
<p>컴퓨터에 메시지를 보내려면 메시지를 받을 특정 컴퓨터를 지정해야합니다. 
따라서 네트워크에 연결된 모든 컴퓨터에는 IP 주소 (IP는 인터넷 프로토콜을 나타냄)라는 고유한 주소가 있고, 주소는 점으로 구분 된 네 개의 숫자로 구성된 주소로 되어있다. 
<code>예: 192.168.2.10.</code></p>
<p>컴퓨터는 이러한 주소로 다른 컴퓨터를 찾아가는데 문제가 없지만, 
우리들은 IP주소를 기억하기 어려우니 <strong>도메인 이름</strong> 이라고하는 사람이 읽을 수 있는 
IP 주소의 이름을 지정할 수 있다. </p>
<p>예를 들어 <strong>google.com</strong>은 IP 주소로 <strong>173.194.121.32</strong> 입니다. 따라서 <strong>도메인 이름</strong>은 <strong>IP주소</strong>보다 인터넷을 사용하기에 쉽다.
<img src="https://velog.velcdn.com/images/j_zero/post/a1f8245e-c38c-4504-b317-376a1ab0170b/image.png" alt=""><br/></p>
<hr>
<h3 id="인터넷과-웹">인터넷과 웹</h3>
<p>웹 브라우저를 사용하여 웹을 탐색 할 때 일반적으로 도메인 이름을 사용하여 웹 사이트에 접속하는데, 이게 인터넷과 웹이 같은 것을 의미하진 않는다.</p>
<p>앞에서 보았듯이 인터넷은 수십억 대의 컴퓨터를 모두 연결하는 기술 인프라이다. 
이러한 컴퓨터들 중에 일부는 <strong>웹 서버</strong>로서 웹 브라우저가 이해할 수 있는 서비스를 제공한다. 인터넷은 인프라이며, 웹은 그 인프라 기반 위에 구축된 서비스입니다. 웹 뿐만 아니라 인터넷 위에 구축된 다른 서비스들(이메일, IRC 등)도 있음을 알아야한다.</p>
<hr>
<h3 id="dns-설명">DNS 설명</h3>
<p>실제 웹 주소는 멋지거나, 여러분이 선호하는 웹사이트를 찾기 위한 주소 막대에 입력하는 기억할만한 문자가 아닙니다. 그것은 63.245.217.105 같은 숫자 덩어리로, 이런 주소를 IP주소라 한다.</p>
<p>웹의 하나뿐인 특정 위치를 나타냅니다. 그러나 기억하기에 쉽지는 않은 형태여서 사람이 쉽게 기억할 수 있는 문자열 형태의 도메인 이름 서버가 발명되었다. 도메인 이름 서버는 여러분이 브라우저에 입력하는 웹주소 <code>mozilla.org</code> 같은 웹사이트의 실제 (IP) 주소에 맞춰주는 특별한 서버이다.</p>
<p>웹사이트는 그들의 IP 주소를 통해 직접 접근할 수도 있다. IP Checker와 같은 도구에 도메인을 입력해 IP 주소를 찾을 수 있습니다.</p>
<hr>
<h3 id="패킷과-프로토콜">패킷과 프로토콜</h3>
<p>우리가 전송하는 데이터로는 텍스트, 이미지 등이 있는데, 통째로 전송하지 않고 작게 나눠서 보낸다.</p>
<p>이 작게 나눈 데이터 조각을 패킷이라고 한다. 
전송되는 패킷은 전자 신호로 변환되어 이더넷 케이블이라는 전선을 먼저 통과해야 한다. </p>
<p>전자 신호는 0과 1로 이루어져 있고, 이 신호를 다른 컴퓨터에 전송하면 
다시 원래의 데이터로 변환해야 하는데, 아무런 양식 없이 전송하면 다른 컴퓨터가 
이 데이터가 텍스트인지 이미지인지 어떻게 변환해야 하는지 알 수 없다. </p>
<p>따라서 데이터를 전송하는 특정 양식(통신 규약)을 정해놓았는데, 이것을 프로토콜이라고 한다. </p>
<p>프로토콜은 장치마다 처리하는 역할마다 다양하다. 
프로토콜을 각 역할로 구분하여 계층을 나눠놓은 것을 TCP/IP 4 Layer라고 한다. 이렇게 구분해 놓으면 서로 간에 간섭을 최소화하여 편리성을 높일 수 있다.</p>
<blockquote>
<p>L4 - 응용(Applicaiton) 계층 (HTTP, FTP, SMTP 등)
웹(HTTP), 이메일(SMTP), 파일전송(FTP) 같은 응용프로그램을 위한 프로토콜</p>
</blockquote>
<blockquote>
<p>L3 - 전송(Transport) 계층 (TCP)
응용프로그램을 구분하는 포트 번호를 통해 컴퓨터에서 돌아가는 프로그램들 중 특정 응용 프로그램 하나를 찾아감</p>
</blockquote>
<blockquote>
<p>L2 - 인터넷(Internet) 계층 (IP)
IP 주소를 통해 수많은 컴퓨터들 중 특정 컴퓨터 하나를 찾아감</p>
</blockquote>
<blockquote>
<p>L1 - 네트워크 연결(Network Accesss) 계층
전선과 장비들을 통해 물리적으로 데이터 전송하기 위해 적절한 디지털/아날로그 신호 등등으로 변환함</p>
</blockquote>
<p>이러한 4개의 계층을 합쳐 TCP/IP 4계층이라고도 한다.</p>
<p>응용 프로그램에서 데이터를 전송하면 각 프로토콜에 따라 패킷이 만들어지고, 
아래 계층으로 내려가며 각 계층의 프로토콜에 따라 해석되거나 다른 정보가 덧붙여져
그 아래 계층으로 내려간다. </p>
<p>네트워크 연결 계층까지 오면 전선과 장치들을 통해 인터넷으로 전송되고, 
아래 계층부터 위 계층까지 차례대로 거쳐 프로토콜에 의해 원본 데이터에 해석된다. </p>
<p>이러한 구분을 통해 서로 간에 간섭이 최소화되어 편하지만, 
응용 계층에서는 응용 프로그램끼리의 해석만 신경 쓰면 되고 그 밑에 
이 응용 프로그램을 어떻게 찾아오는지, 컴퓨터를 어떻게 찾아가는지, 디지털/아날로그 신호로 어떻게 바꾸는지 신경 쓰지 않아도 되기 때문이다.</p>
<hr>
<h2 id="✏️reference">✏️Reference</h2>
<ul>
<li><a href="https://developer.mozilla.org/ko/docs/Learn/Common_questions/Web_mechanics/How_does_the_Internet_work#%EB%8B%A4%EC%9D%8C_%EB%8B%A8%EA%B3%84">https://developer.mozilla.org/ko/docs/Learn/Common_questions/Web_mechanics/How_does_the_Internet_work#%EB%8B%A4%EC%9D%8C_%EB%8B%A8%EA%B3%84</a></li>
<li><a href="https://gyunny.tistory.com/2#">https://gyunny.tistory.com/2#</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[LeetCode - 136(JS, Easy)]]></title>
            <link>https://velog.io/@j_zero/LeetCode-136JS-Easy</link>
            <guid>https://velog.io/@j_zero/LeetCode-136JS-Easy</guid>
            <pubDate>Wed, 10 Apr 2024 14:42:47 GMT</pubDate>
            <description><![CDATA[<h1 id="136-single-number">136. Single Number</h1>
<h3 id="문제">문제</h3>
<p><img src="https://velog.velcdn.com/images/j_zero/post/057d7944-be29-43d3-9aaf-67b55551575b/image.png" alt=""></p>
<h3 id="설명">설명</h3>
<blockquote>
<p>정수형 배열 <code>nums</code>에서 유일한 수를 반환하면 된다.</p>
</blockquote>
<h3 id="풀이">풀이</h3>
<pre><code class="language-js">/**
 * @param {number[]} nums
 * @return {number}
 */
var singleNumber = function(nums) {
    let uniqueNum = 0;

    for(let i = 0; i &lt; nums.length; i++){
        uniqueNum ^= nums[i];
    }

    return uniqueNum;
};</code></pre>
<blockquote>
<p>XOR연산을 이용한 풀이이다. 조건에서 
<code>Each element in the array appears twice except for one element which appears only once.</code> 각 요소는 한 번만 나타나는 요소를 제외하고 두 번 나타난다는 것을 알 수 있다.
1 ^ 1 = 0001(2) ^ 0001(2) = 0000(0) 같은 수를 두 번 xor 연산하면 0이 나오는 것을 이용해 고유한 수를 찾을 수 있다.</p>
</blockquote>
<pre><code class="language-c">Example 1:
i: 0, unique: 0000(0) ^ 0010(2) = 0010(2)
i: 1, unique: 0010(2) ^ 0010(2) = 0000(0)
i: 2, unique: 0000(1) ^ 0001(1) = 0001(1)

// output: 1

----------------------------------------------------

Example 2:
i: 0, unique: 0000(0) ^ 0100(4) = 0100(4)
i: 1, unique: 0100(4) ^ 0001(1) = 0101(5)
i: 2, unique: 0101(5) ^ 0010(2) = 0111(7)
i: 3, unique: 0111(7) ^ 0001(1) = 0110(6)
i: 4, unique: 0110(6) ^ 0010(2) = 0100(4)

// output 4</code></pre>
<blockquote>
<p>위의 연산 과정을 보면 같은 수를 두 번 XOR 연산하게 되면 0으로 무산되는 것을 알 수 있다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[LeetCode - 189(JS, Medium)]]></title>
            <link>https://velog.io/@j_zero/LeetCode-189JS-Medium</link>
            <guid>https://velog.io/@j_zero/LeetCode-189JS-Medium</guid>
            <pubDate>Wed, 10 Apr 2024 13:38:54 GMT</pubDate>
            <description><![CDATA[<h1 id="189-rotate-array">189. Rotate Array</h1>
<h3 id="문제">문제</h3>
<p><img src="https://velog.velcdn.com/images/j_zero/post/cb53c8f3-3e80-4a97-9248-2d160b06cdfb/image.png" alt=""></p>
<h3 id="설명">설명</h3>
<blockquote>
<p>정수형 배열 <strong>nums</strong>을 <strong>k</strong>번 오른쪽으로 회전시키면 되는 문제다.</p>
</blockquote>
<h3 id="풀이">풀이</h3>
<pre><code class="language-js">/**
 * @param {number[]} nums
 * @param {number} k
 * @return {void} Do not return anything, modify nums in-place instead.
 */
var rotate = function(nums, k) {
    if(nums.length === 1) return;
    if(k === 0) return;

    let arr = JSON.parse(JSON.stringify(nums));
    let temp = k % arr.length;

    let idx = arr.length - temp;
    for(let i = 0; i &lt; arr.length; i++){
        nums[i] = arr[(idx+i) % arr.length];
    }
};</code></pre>
<blockquote>
<p>그냥 원소를 한 칸씩 밀기엔 시간복잡도가 <strong>O(nums.length * k)</strong> 이 되기 때문에
원본 배열을 복사해두고 <code>k</code>가 <code>nums.length</code>보다 클 경우 <code>(k % nums.length)</code>번 회전한 결과와 같기에 <code>k</code>는 <code>nums.length</code>로 나눈 나머지로 바꿨다.
<code>Example 1</code>와 <code>Example 2</code>를 보면 <code>output</code>이 원본 배열의 <code>nums.length - k</code>번째부터 하나씩 넣은 결과와 같이 때문에 이 점에 초점을 두고 <code>nums</code>의 원소를 변경했다.
arr를 참조하면서 <strong>IndexOutOfBoundsException</strong>가 일어나지 않게 arr.length로 나눈 나머지를 넣었다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[LeetCode - 1051(JS, Easy)]]></title>
            <link>https://velog.io/@j_zero/LeetCode-1051JS-Easy</link>
            <guid>https://velog.io/@j_zero/LeetCode-1051JS-Easy</guid>
            <pubDate>Sun, 07 Apr 2024 13:47:19 GMT</pubDate>
            <description><![CDATA[<h1 id="1051-height-checker">1051. Height Checker</h1>
<h3 id="문제">문제</h3>
<p><img src="https://velog.velcdn.com/images/j_zero/post/a64c5ef3-b75b-469e-b522-91ff0b25f064/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/j_zero/post/2b2c2308-4202-4f65-b3d7-8414eb5cfb37/image.png" alt=""></p>
<h3 id="설명">설명</h3>
<blockquote>
<p>정수형 배열 <strong>heights</strong>가 주어지고 <strong>heights</strong>를 오름차순으로 정렬한 배열과 비교했을때 일치하지 않은 횟수 반환하면 됨.</p>
</blockquote>
<h3 id="풀이">풀이</h3>
<pre><code class="language-js">/**
 * @param {number[]} heights
 * @return {number}
 */
var heightChecker = function(heights) {

    // 배열 복사(그냥 대입하면 얕은 복사가 되기에 깊은 복사로 넣는다.) 및 오름차순 정렬
    let sortedArr = [...heights].sort((a,b) =&gt; (a-b));

    // 비교
    let cnt = 0;

    for(let i = 0; i &lt; heights.length; i++){
        if(heights[i] !== sortedArr[i]) cnt++;
    }

    return cnt;
};</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[LeetCode - 26(JS, Easy)]]></title>
            <link>https://velog.io/@j_zero/LeetCode-26JS-Easy</link>
            <guid>https://velog.io/@j_zero/LeetCode-26JS-Easy</guid>
            <pubDate>Fri, 05 Apr 2024 14:10:25 GMT</pubDate>
            <description><![CDATA[<h1 id="26-remove-duplicates-from-sorted-array">26. Remove Duplicates from Sorted Array</h1>
<h3 id="문제">문제</h3>
<p><img src="https://velog.velcdn.com/images/j_zero/post/84080a63-ec0d-4778-9b2a-79d12f1943ae/image.png" alt=""></p>
<h3 id="설명">설명</h3>
<blockquote>
<p>정수형 배열 <strong>nums</strong>이 주어지고 In-place를 활용해 각각 고유한 원소만 있는 배열로 수정 후 배열의 길이를 반환하면 된다.</p>
</blockquote>
<h3 id="풀이">풀이</h3>
<pre><code class="language-js">/**
 * @param {number[]} nums
 * @return {number}
 */
var removeDuplicates = function(nums) {
      // 1개짜리 배열은 바로 리턴
    if(nums.length === 1) return 1;

      // 기준이 될 pointer1과 비교할 pointer2를 선언
    let pointer1 = 0, pointer2;
    for(let i = 1; i &lt; nums.length; i++){
        pointer2 = i;

          // 원소 검사 중 중복되지 않는 원소가 나오면
        if(nums[pointer1] !== nums[pointer2]){
              /*
             * 기준이 되던 nums[pointer1]의 바로 뒤 원소를 nums[pointer2]로
             * 바꾼 후 pointer1를 한 칸 뒤로 변경
             */
            nums[pointer1 + 1] = nums[pointer2];
            ++pointer1;
        }
    }

    nums.length = pointer1 + 1;

    return nums.length;
};</code></pre>
<p><img src="https://leetcode.com/explore/learn/card/fun-with-arrays/511/in-place-operations/Figures/Array_Explore/inplace-3.png" alt="풀이 추가 설명" title="풀이 추가설명"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[LeetCode - 88(JS, Easy)]]></title>
            <link>https://velog.io/@j_zero/LeetCode-88JS-Easy</link>
            <guid>https://velog.io/@j_zero/LeetCode-88JS-Easy</guid>
            <pubDate>Fri, 05 Apr 2024 13:32:08 GMT</pubDate>
            <description><![CDATA[<h1 id="88-merge-sorted-array">88. Merge Sorted Array</h1>
<h3 id="문제">문제</h3>
<p><img src="https://velog.velcdn.com/images/j_zero/post/4fe042c1-96fd-423e-aa33-ac59ff1cb49c/image.png" alt=""></p>
<h3 id="설명">설명</h3>
<blockquote>
<p><strong>감소되지 않는</strong> 두 정수형 배열 nums1, nums2와 정수 m, n이 주어진다. 두 정수형 배열을 <strong>0</strong>을 제외한 나머지 값들만 병합해서 <strong>nums1에 저장하면 <img src="https://velog.velcdn.com/images/j_zero/post/ced77370-dfc5-45f6-b0bc-548f1865424f/image.png" alt="">
<img src="https://velog.velcdn.com/images/j_zero/post/68633aae-a097-4ef3-97c8-c81566732493/image.png" alt="">
된다.</strong>
m은 nums1의 병합되어야 하는 원소의 개수고, n은 무시해야 하는 0의 개수이고, nums2의 길이이기도 하다.</p>
</blockquote>
<h3 id="풀이">풀이</h3>
<pre><code class="language-js">/**
 * @param {number[]} nums1
 * @param {number} m
 * @param {number[]} nums2
 * @param {number} n
 * @return {void} Do not return anything, modify nums1 in-place instead.
 */
var merge = function(nums1, m, nums2, n) {
      /**
     * nums1의 m번째부터 0으로 n개 채워져있으니
     * 그 부분을 nums2의 원소로 변경한다.
     */
    for(let i = 0; i &lt; n; i++){
        nums1[m+i] = nums2[i];
    }

      // 이후 배열을 오름차순으로 정렬한다.
    nums1.sort((a,b) =&gt; (a-b));
};</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[LeetCode - 1299(JS, Easy)]]></title>
            <link>https://velog.io/@j_zero/LeetCode-1299JS-Easy</link>
            <guid>https://velog.io/@j_zero/LeetCode-1299JS-Easy</guid>
            <pubDate>Fri, 05 Apr 2024 13:22:49 GMT</pubDate>
            <description><![CDATA[<h1 id="1299-replace-elements-with-greatest-element-on-right-side">1299. Replace Elements with Greatest Element on Right Side</h1>
<h3 id="문제">문제</h3>
<p><img src="https://velog.velcdn.com/images/j_zero/post/20855bbc-0aef-438d-956d-7827517578e9/image.png" alt=""></p>
<h3 id="설명">설명</h3>
<blockquote>
<p>정수형 배열이 주어지고 <strong>arr[i]</strong>의 값을 <strong>arr[i+1] ~ arr[arr.length]</strong> 까지의 값 중에서 가장 큰 수로 바꿔주면 된다. 가장 마지막에 있는 원소는 <strong>-1</strong>로 바꿔주면 된다.</p>
</blockquote>
<h3 id="풀이">풀이</h3>
<pre><code class="language-js">/**
 * @param {number[]} arr
 * @return {number[]}
 */
var replaceElements = function(arr) {
      // 배열 원소가 하나인 경우
    if(arr.length == 1) arr[0] = -1;

    for(let i = 0; i &lt; arr.length; i++){
        // 마지막 원소는 -1로 고정
          if(i === arr.length-1) {
            arr[i] = -1;
            break;
        }

        let max = 0;
        // arr[i]보다 뒤에 있는 원소 값 중 최고값 찾기
        for(let j = i + 1; j &lt; arr.length; j++){
            if(max &lt; arr[j]) max = arr[j];
        }

        arr[i] = max;
    }

    return arr;
};
```![](https://velog.velcdn.com/images/j_zero/post/341195b2-6096-4e1b-a883-7f4b702fe56a/image.png)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[LeetCode - 1089(JS, Easy)]]></title>
            <link>https://velog.io/@j_zero/LeetCode-1089JS-Easy</link>
            <guid>https://velog.io/@j_zero/LeetCode-1089JS-Easy</guid>
            <pubDate>Wed, 03 Apr 2024 14:56:01 GMT</pubDate>
            <description><![CDATA[<h2 id="1089-duplicate-zeros">1089. Duplicate Zeros</h2>
<blockquote>
<p>난이도: Easy</p>
</blockquote>
<h3 id="문제">문제</h3>
<p><img src="https://velog.velcdn.com/images/j_zero/post/34a2ea76-cc74-48a7-92b9-837018e5c594/image.png" alt=""></p>
<h3 id="설명">설명</h3>
<blockquote>
<p><strong>길이가 고정된 정수형 배열</strong>이 주어진다. 원소 중에 0이 있으면 해당 원소 뒤에 0을 삽입하면 된다.</p>
</blockquote>
<h3 id="풀이">풀이</h3>
<pre><code class="language-js">/**
 * @param {number[]} arr
 * @return {void} Do not return anything, modify arr in-place instead.
 */
var duplicateZeros = function(arr) {
    let temp = [];

    for(let i = 0; i &lt; arr.length; i++){
        temp.push(arr[i]);
        if(arr[i] == 0) temp.push(0);
    }

    for(let i = 0; i &lt; arr.length; i++){
        arr[i] = temp[i];
    }
};</code></pre>
<blockquote>
<p>원소 0뒤에 추가로 0을 넣은 배열 <strong>temp</strong>를 생성하고 기존 배열 <strong>arr</strong>의 길이만큼 <strong>temp</strong>를 잘라서 넣는다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[LeetCode - 977(JS, Easy)]]></title>
            <link>https://velog.io/@j_zero/LeetCode-977JS-Easy</link>
            <guid>https://velog.io/@j_zero/LeetCode-977JS-Easy</guid>
            <pubDate>Wed, 03 Apr 2024 14:49:56 GMT</pubDate>
            <description><![CDATA[<h2 id="977-squares-of-a-sorted-array">977. Squares of a Sorted Array</h2>
<blockquote>
<p>난이도: Easy</p>
</blockquote>
<h3 id="문제">문제</h3>
<p><img src="https://velog.velcdn.com/images/j_zero/post/e6a1c146-703f-421c-8e12-98be7a437214/image.png" alt=""></p>
<h3 id="설명">설명</h3>
<blockquote>
<p>정수로 된 <strong>감소되지 않는 배열</strong>이 주어지는데 이 배열의 요소들을 <strong>제곱</strong>한 후 오름차순으로 정렬하면 된다.</p>
</blockquote>
<h3 id="풀이">풀이</h3>
<pre><code class="language-js">/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortedSquares = function(nums) {

    for(let i = 0; i &lt; nums.length; i++){
        nums[i] = nums[i] * nums[i];
    }

    nums.sort((a,b) =&gt; (a - b));
    return nums;
};</code></pre>
<blockquote>
<p>각 배열의 원소를 제곱한 후 sort 메서드로 오름차순 정렬했다. sort안의 콜백함수의 리턴이 1이면 a,b를 서로 교환하고, -1이면 넘어간다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[LeetCode - 383(JS, Easy)]]></title>
            <link>https://velog.io/@j_zero/LeetCode-383JS-Easy</link>
            <guid>https://velog.io/@j_zero/LeetCode-383JS-Easy</guid>
            <pubDate>Mon, 01 Apr 2024 14:32:27 GMT</pubDate>
            <description><![CDATA[<h2 id="383-ransom-note">383. <a href="https://leetcode.com/problems/ransom-note/" title="Ransom Note">Ransom Note</a></h2>
<blockquote>
<p>난이도: Easy</p>
</blockquote>
<h3 id="문제해설">문제해설</h3>
<blockquote>
<p>Given two strings <code>ransomNote</code> and <code>magazine</code>, return <code>true</code> if <code>ransomNote</code> can be constructed by using the letters from <code>magazine</code> and <code>false</code> otherwise.
Each letter in <code>magazine</code> can only be used once in <code>ransomNote</code>.</p>
</blockquote>
<h3 id="해답">해답</h3>
<pre><code class="language-js">/**
 * @param {string} ransomNote
 * @param {string} magazine
 * @return {boolean}
 */
var canConstruct = function(ransomNote, magazine) {
    for(const char of magazine){
        ransomNote = ransomNote.replace(char, &quot;&quot;);
    }

    if(ransomNote === &#39;&#39;) return true;
    else return false;
};</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[LeetCode - 876(JS, Easy)]]></title>
            <link>https://velog.io/@j_zero/LeetCode-876JS-Easy</link>
            <guid>https://velog.io/@j_zero/LeetCode-876JS-Easy</guid>
            <pubDate>Mon, 01 Apr 2024 14:12:19 GMT</pubDate>
            <description><![CDATA[<h2 id="876-middle-of-the-linked-list">876. Middle of the Linked List</h2>
<blockquote>
<p>난이도: Easy</p>
</blockquote>
<h3 id="문제해설">문제해설</h3>
<blockquote>
<p>Given the head of a singly linked list, return the middle node of the linked list.
If there are two middle nodes, return the second middle node.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/j_zero/post/601259a7-ac3d-449a-bac8-3cad08293097/image.png" alt=""></p>
<h3 id="해답">해답</h3>
<pre><code class="language-js">/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var middleNode = function(head) {
    let listLength = 0;
    let pointer = head; // Linked List 포인터

      // head의 Node개수 세기
    while(pointer.next != null){
        pointer = pointer.next;
        ++listLength;
    }

    pointer = head;
    // list의 중간지점으로 이동    
      for(let i = 0; i &lt; listLength / 2; i++){
        pointer = pointer.next;
    }

    return pointer;
};</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[LeetCode - 412(JS, Easy)]]></title>
            <link>https://velog.io/@j_zero/LeetCode-412JS-Easy</link>
            <guid>https://velog.io/@j_zero/LeetCode-412JS-Easy</guid>
            <pubDate>Mon, 01 Apr 2024 13:59:42 GMT</pubDate>
            <description><![CDATA[<h2 id="412-fizz-buzz">412. <a href="https://leetcode.com/problems/fizz-buzz/" title="Fizz Buzz">Fizz Buzz</a></h2>
<blockquote>
<p>난이도: Easy</p>
</blockquote>
<h3 id="문제해설">문제해설</h3>
<blockquote>
<p>Given an integer n, return a string array answer (1-indexed) where:</p>
</blockquote>
<ul>
<li><code>answer[i] == &quot;FizzBuzz&quot; if i is divisible by 3 and 5.</code></li>
<li><code>answer[i] == &quot;Fizz&quot; if i is divisible by 3.</code></li>
<li><code>answer[i] == &quot;Buzz&quot; if i is divisible by 5.</code></li>
<li><code>answer[i] == i (as a string) if none of the above conditions are true.</code></li>
</ul>
<h3 id="정답">정답</h3>
<pre><code class="language-js">/**
 * @param {number} n
 * @return {string[]}
 */
var fizzBuzz = function(n) {
    let arr = [];

    for(let i = 1; i &lt;=n; i++){
        if(i % 15 == 0) {
            arr[i-1] = &quot;FizzBuzz&quot;;
        }
        else if(i % 3 == 0){
            arr[i] = &quot;Fizz&quot;;
        }
        else if(i % 5 == 0){
            arr[i] = &quot;Buzz&quot;;
        }
        else{
            arr[i] = i.toString();
        }
    }

    arr.shift();
    return arr;
};</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[LeetCode - 1672(JS, Easy)]]></title>
            <link>https://velog.io/@j_zero/LeetCode-1672JS-Easy</link>
            <guid>https://velog.io/@j_zero/LeetCode-1672JS-Easy</guid>
            <pubDate>Mon, 01 Apr 2024 13:50:58 GMT</pubDate>
            <description><![CDATA[<h3 id="1672-richest-customer-wealth">1672. Richest Customer Wealth</h3>
<blockquote>
<p>난이도: Easy</p>
</blockquote>
<h3 id="문제해설">문제해설</h3>
<blockquote>
<p>You are given an <code>m</code> x <code>n</code> integer grid <code>accounts</code> where <code>accounts[i][j]</code> is the amount of money the <code>i</code>th customer has in the <code>j</code>th bank. Return the <strong>wealth</strong> that the richest customer has.
A customer&#39;s <strong>wealth</strong> is the amount of money they have in all their bank accounts. The richest customer is the customer that has the maximum <strong>wealth</strong>.</p>
</blockquote>
<h3 id="정답">정답</h3>
<pre><code class="language-js">/**
 * @param {number[][]} accounts
 * @return {number}
 */
var maximumWealth = function(accounts) {
    let row = accounts.length;
    let col = accounts[0].length;
    let max = 0;
    for(let i = 0; i &lt; row; i++){
        let temp = 0;
        for(let j = 0; j &lt; col; j++){
            temp += accounts[i][j];
            if(max &lt; temp) max = temp;
        }
    }

    return max;
};</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[LeetCode - 1480(JS, Easy)]]></title>
            <link>https://velog.io/@j_zero/LeetCode-1480JS</link>
            <guid>https://velog.io/@j_zero/LeetCode-1480JS</guid>
            <pubDate>Mon, 01 Apr 2024 13:27:24 GMT</pubDate>
            <description><![CDATA[<h2 id="1480-running-sum-of-1d-array">1480. Running Sum of 1d Array</h2>
<blockquote>
<p>난이도: Easy</p>
</blockquote>
<h3 id="문제-설명">문제 설명</h3>
<blockquote>
<p>Given an array nums. We define a running sum of an array as 
runningSum[i] = sum(nums[0]…nums[i]).
Return the running sum of nums.</p>
</blockquote>
<h3 id="해설">해설</h3>
<blockquote>
<p>배열 nums가 입력되고 새로운 배열 <strong>runningSum</strong>을 만드는데 
<strong>runningSum의 i번째 요소가 sum(nums[0]...nums[i])여야 한다</strong>. 
구한 <strong>runningSum을 반환하면 된다.</strong></p>
</blockquote>
<h3 id="정답">정답</h3>
<pre><code class="language-js">/**
 * @param {number[]} nums
 * @return {number[]}
 */
var runningSum = function(nums) {
    let arr = []
    let sum = 0;
    for(let i = 0; i &lt; nums.length; i++){
        sum += nums[i];
        arr.push(sum);
    }

    return arr;
};</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[LeetCode - 1342(JS, Easy)]]></title>
            <link>https://velog.io/@j_zero/LeetCode-1342JS</link>
            <guid>https://velog.io/@j_zero/LeetCode-1342JS</guid>
            <pubDate>Mon, 01 Apr 2024 13:14:42 GMT</pubDate>
            <description><![CDATA[<h2 id="1342-number-of-steps-to-reduce-a-number-to-zero">1342. Number of Steps to Reduce a Number to Zero</h2>
<blockquote>
<p>난이도: Easy</p>
</blockquote>
<h3 id="문제-설명">문제 설명</h3>
<blockquote>
<p>Given an integer num, return the number of steps to reduce it to zero.
In one step, if the current number is even, you have to divide it by 2, otherwise, you have to subtract 1 from it.</p>
</blockquote>
<h3 id="해석">해석</h3>
<blockquote>
<p>정수 $$num$$ $$(0 &lt;= num &lt;= 10^6$$)이 입력된다. 정수가 짝수면 2로 나누고 홀수면 1로 빼야한다.
정수 $$num$$이 0이 될 때까지 걸린 연산의 횟수를 반환해라.</p>
</blockquote>
<h3 id="정답">정답</h3>
<pre><code class="language-js">/**
 * @param {number} num
 * @return {number}
 */
var numberOfSteps = function(num) {
    let answer = 0;

    while(num != 0){
        if(num % 2 === 0) num /= 2;
        else num -= 1;

        ++answer;
    }

    return answer;
};</code></pre>
]]></description>
        </item>
    </channel>
</rss>