<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>hotteok_.log</title>
        <link>https://velog.io/</link>
        <description>성장하는 Front-End 개발자를 목표로!(✿◡‿◡)</description>
        <lastBuildDate>Fri, 30 Aug 2024 06:45:01 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>hotteok_.log</title>
            <url>https://velog.velcdn.com/images/hotteok_/profile/95429b2a-d2bc-41bb-921b-3ccdf9675899/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. hotteok_.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/hotteok_" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[재귀(Recursion)]]></title>
            <link>https://velog.io/@hotteok_/%EC%9E%AC%EA%B7%80Recursion</link>
            <guid>https://velog.io/@hotteok_/%EC%9E%AC%EA%B7%80Recursion</guid>
            <pubDate>Fri, 30 Aug 2024 06:45:01 GMT</pubDate>
            <description><![CDATA[<h1 id="🔄-재귀---recursion">🔄 재귀 - Recursion</h1>
<blockquote>
<p>어떠한 것을 정의할 때 자기 자신을 참조하는 것을 뜻한다. 즉, 자기 자신을 호출하는 절차</p>
</blockquote>
<h2 id="1-재귀가-쓰이는-곳">1. 재귀가 쓰이는 곳</h2>
<ol>
<li>재귀는 큰 목표 작업 하나를 동일하면서 간단한 작업 여러 개로 나눌 수 있을 때</li>
<li>javascript 내부에서는?</li>
</ol>
<ul>
<li>JSON.parse / JSON.stringify</li>
<li>document.getElementById, querySelector and DOM 탐색 알고리즘(*DOM은 요소가 중첩된 트리 구조)</li>
</ul>
<ol start="3">
<li>객체 순회</li>
<li>복잡한 데이터 구조 (데이터 구조, 트리, 그래프)를 순회, 그 안에 있는 요소 검색 하는 경우</li>
</ol>
<p><br><br></p>
<h3 id="✋-잠깐-재귀를-이해하려면-call-stack에-대해-알아야함">✋ 잠깐! 재귀를 이해하려면 Call Stack에 대해 알아야함</h3>
<ul>
<li>JavaScript는 단일 스레드 프로그래밍 언어이므로, 단일 호출 스택이 존재. 
=&gt;한 번에 하나의 일(Task)만 처리할 수 있다</li>
<li>함수를 실행하면 해당 함수의 기록을 스택 맨 위에 추가(Push) ,
함수를 결과 값을 반환(함수가 종료)하면 스택에 쌓여있던 함수는 제거(Pop)되며 동작한다.</li>
</ul>
<p>** <span style="font-size: 15px; margin-left:30px; color: gray"> 지금은 간단히 기록, 따로 콜스텍과 자바스크립트 엔진이 돌아가는 원리에 대해서 정리해 볼 예정이다!!!</span>**</p>
<h2 id="2-재귀-함수-recursion-function">2. 재귀 함수 (Recursion Function)</h2>
<blockquote>
<p>동일한 함수를 계속 호출하면서 하나의 함수가 자신을 재귀적으로 호출
 (중단 포인트를 만날 때 까지 같은 함수를 계속 호출)</p>
<pre><code> * 중단 조건 필수 -&gt; stack overflow 현상이 일어남

 * 매번 다른 input을 통해 호출되어야한다.</code></pre></blockquote>
<h2 id="2-1-재귀-함수의-잠재적-위험성을-초래하는-문제점">2-1. 재귀 함수의 잠재적 위험성을 초래하는 문제점</h2>
<p> *<em>1. 종료 조건이 없거나 잘못 되는 경우 *</em></p>
<ul>
<li>함수가 종료되지 않고 stack overflow로 종료됨 (엔진마다 호출 스택 크기가 정해져 있기 때문에) <pre><code>return 으로 확실한 break point(base case)를 설정해줘야 한다.</code></pre></li>
</ul>
<p>** 2. 값을 반환하는 걸 잊는 것 **</p>
<ul>
<li>call stack의 경우 모든 항목이 서로에게 의존적이며 연결되어 있다 마지막에는 어떤 값을 도출해서 그 값을 돌려보내야 한다</li>
</ul>
<p><strong>3. 잘못된 값을 반환 하는 것</strong></p>
<br>
<br>


<h3 id="💻-예제1">💻 예제1</h3>
<blockquote>
<p> num까지의 합을 리턴하는 함수 sumRange를 작성하시오</p>
</blockquote>
<pre><code class="language-jsx">const sumRange = (num) =&gt; {
  if (num === 1) return 1; //base case (중단 조건)
  return num + sumRange(num - 1); // 재귀호출 : 매번 더 작은 값으로 input 값을 받음
};</code></pre>
<h3 id="💡-예제1-실행순서">💡 예제1 실행순서</h3>
<p> <strong>실행순서 3</strong> &gt;&gt; <code>return 3 + sumRange(2)</code>
 <strong>실행순서 2</strong> &gt;&gt;  ...................   <code>return 2 + sumRange(1)</code>
 <strong>실행순서 1</strong> &gt;&gt;  ............................................  <code>return 1</code>    </p>
<p> <code>call stack의 상단의 연산부터 시작해 sumRage(1)의 리턴값 (재귀 종료)인 1부터 순서대로  ((1) + 2)+ 3 순서대로 sum 후 리턴</code></p>
<p> <img src="https://velog.velcdn.com/images/hotteok_/post/9541013c-ec36-4940-b22f-50e6936fb099/image.png" align="left" width="300" alt></p>


<br>
<br>

<br>
<br>

<br>
<br>

<br>
<br>

<br>
<br>

<br>
<br>

<br>
<br>

<h3 id="💻-예제2">💻 예제2</h3>
<blockquote>
<p>Factorial 구하는 함수</p>
<pre><code>팩토리얼 = 계승 : 1부터 n까지의 자연수를 모두 곱하는 것</code></pre></blockquote>
<p>** 풀어보기 전 ** </p>
<ol>
<li>num이 1이 되면 멈춘다 (0이되면 어떤 수든 리턴 값이 0이 됨)</li>
<li>숫자를 1씩 줄여가면서 재귀 함수 호출 * 인자로 받은 num 곱해줌 =&gt; num이 1이 될 때 까지 재귀 호출</li>
</ol>
<pre><code class="language-jsx">const getFactorial = (num) =&gt; {
  if (num === 1) return 1;
  return num * getFactorial(num - 1);
};</code></pre>
<h2 id="3-helper-method-function">3. Helper Method Function</h2>
<blockquote>
<p>재귀적이지 않은 외부 함수가 재귀적인 내부 함수(inner function)을 호출하는 패턴이다. 문제 해결을 위한 하나의 접근법이다. </p>
</blockquote>
<ol>
<li>헬퍼 함수 혹은 헬퍼 메소드 재귀라고 부른다. </li>
<li>메인 외부 함수를 개발자가 외부에서 호출한다. </li>
<li>이 외부 함수를  호출할 때 인자를 내부로 전달해 줄 수 있다. </li>
<li>이 외부 함수 내부에는 또 다른 내부 함수가 정의되어 있다. 내부함수는 호출되고 재귀적으로 자기자신을 호출한다. </li>
<li>결과를 컴파일할 때 흔히 사용 결과는 배열과 다른 형태의 데이터 구조이다.</li>
</ol>
<br>
<br>

<p><strong>기본형태</strong></p>
<pre><code class="language-jsx">const outer = (input) =&gt; {
  const outerScopedVar = []; // array or list of data

  const helper = (helperInput) =&gt; {
    //outerScopedVar 변경
    helper(helperInput--); // 인풋 값 감소
  };

  helper(input);

  return outerScopedVar;
};</code></pre>
<h3 id="💻-사용-예">💻 사용 예</h3>
<blockquote>
<p>어느 배열에서 홀수 값을 구하는 것 같은 작업</p>
</blockquote>
<pre><code class="language-jsx">const collectOddValues = (arr) =&gt; {
  const result = [];

  const helper = (helperInput) =&gt; {
    if (helperInput.length === 0) return;

    if (helperInput[0] % 2 !== 0) result.push(helperInput[0]);

    helper(helperInput.slice(1));
  };

  helper(arr);

  return result;
};



//재귀 함수를 내부 호출히서 쓰는 위의 패턴이 아닌 재귀만 사용해서 풀이

const collectOddValues2 = (arr) =&gt; {
  let newArr = []; // 내부에 요소를 추가해주는 게 아닌 배열을 합쳐서 새 배열을 할당해야 하므로 let으로 선언

  if (arr.length === 0) return newArr;

  if (arr[0] % 2 !== 0) {
    newArr.push(arr[0]);
  }
  console.log(newArr);
  newArr = newArr.concat(collectOddValues2(arr.slice(1)));

  return newArr;
};

</code></pre>
<p><strong>collectOddValues2([1,2,3,4,5]) 재귀 동작 방식</strong></p>
<p><strong>실행완료순서6 &gt;&gt;</strong> <code>[1].concat(collectOddValues2([2,3,4,5]))</code>
<strong>실행완료순서5 &gt;&gt; ......</strong> <code>[].concat(collectOddValues2([3,4,5]))</code>
<strong>실행완료순서4 &gt;&gt; ............</strong> <code>[3].concat(collectOddValues2([4,5]))</code>
<strong>실행완료순서3 &gt;&gt; ..................</strong> <code>[].concat(collectOddValues2([5]))</code>
<strong>실행완료순서2 &gt;&gt; ........................</strong> <code>[5].concat(collectOddValues2([]))</code> 
<strong>실행완료순서1 &gt;&gt; ................................</strong> <code>[]</code></p>
<h2 id="3-순수하게-재귀-함수만-사용하여-구성할-때-사용하는-method">3. 순수하게 재귀 함수만 사용하여 구성할 때 사용하는 Method</h2>
<blockquote>
<p>자료형에 맞게 복사본을 만들어 진행 =&gt; 변경 할 필요 없음 , 결과를 축적할 수 있음</p>
</blockquote>
<ol>
<li><p>array : array.slice(), spread operator , array.concat()와 같은 배열을 복사하는 메서드를 사용</p>
</li>
<li><p>String : immutable(변경할 수 없음)하기에 slice, substr, substring 같은 메서드를 통해 문자열의 사본을 만들어 진행</p>
</li>
<li><p>Object :  Object.assign , spread operator를 이용해 복사본 만들어 사용</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[역지오코딩(Reverse geocoding) - feat. google API...]]></title>
            <link>https://velog.io/@hotteok_/%EC%97%AD%EC%A7%80%EC%98%A4%EC%BD%94%EB%94%A9Reverse-geocoding-feat.-google-API</link>
            <guid>https://velog.io/@hotteok_/%EC%97%AD%EC%A7%80%EC%98%A4%EC%BD%94%EB%94%A9Reverse-geocoding-feat.-google-API</guid>
            <pubDate>Thu, 29 Aug 2024 10:30:23 GMT</pubDate>
            <description><![CDATA[<p>❗️삽질❗️을 많이 했기 때문에 일단 trouble shooting으로 분류했다.. ㅎㅎㅋ...</p>
<p>ReactNative로 날씨 어플 만들기.. ReactNative로 만들어 보고 싶은 어플이 있기 때문에 처음부터 차근차근 배워보고자 시작했다.</p>
<p>인강은 with 니꼬쌤!😎</p>
<hr>
<p>개발 플랫폼 : Expo-CLI
third party : Expo SDK 51 사용</p>
<pre><code class="language-json">//package.json
   &quot;dependencies&quot;: {
    &quot;expo&quot;: &quot;~51.0.28&quot;,
    &quot;expo-status-bar&quot;: &quot;~1.12.1&quot;,
    &quot;react&quot;: &quot;18.2.0&quot;,
    &quot;react-native&quot;: &quot;0.74.5&quot;,
    &quot;expo-location&quot;: &quot;~17.0.1&quot;
  },</code></pre>
<hr>
<h2 id="🤢-맞닥뜨린-문제">🤢 맞닥뜨린 문제</h2>
<pre><code class="language-jsx">import { useEffect, useState } from &#39;react&#39;;
import * as Location from &#39;expo-location&#39;;

export default function App() {
  const [location, setLocation] = useState(null);
  const [city, setCity] = useState(&#39;...loading&#39;);
  const [placeId, setPlaceID] = useState(null);
  const [ok, setOk] = useState(false);

    const { status } = await Location.requestForegroundPermissionsAsync();

    if (status !== &#39;granted&#39;) {
      return;
    }

    setOk((prev) =&gt; !prev);

    const {
      coords: { latitude, longitude },
    } = await Location.getCurrentPositionAsync({ accuracy: 5 });

    setLocation({ latitude, longitude });

//...코드는 일부만 가져옴
</code></pre>
<ul>
<li>현재 기기의 위치를 갖고 오기 위해 <a href="https://docs.expo.dev/versions/latest/sdk/location/#locationrequestforegroundpermissionsasync">Location.requestForegroundPermissionsAsync()</a> 을 사용해서 권한을 먼저 요청 후 <a href="https://docs.expo.dev/versions/latest/sdk/location/#locationgetcurrentpositionasyncoptions">Location.getCurrentPositionAsync()</a>을 이용해 현재 기기 기준의 위치값을 가져와 필요한 위도(latitude) 경도(longitude) 값을 불러온다.<ul>
<li>accuracy 옵션 (1~6까지의 수치로 설정 가능)을 이용해 위치정확성을 조절할 수 있다.</li>
</ul>
</li>
</ul>
<ul>
<li>그리고 그 위도와 경도 값을 <a href="https://docs.expo.dev/versions/latest/sdk/location/#locationreversegeocodeasynclocation-options">Location.reverseGeocodeAsync()</a> 이용 해 지역명(주소지)을 아래와 같이 가져오려 했다.</li>
</ul>
<pre><code class="language-jsx">const response = await Location.reverseGeocodeAsync({location.latitude,location.longitude},{useGoogleMaps:false});</code></pre>
<p>옵션을 사용하지 않는다 했음에도 불러와지지 않는 오류.. 이거 나의 문제일까..?</p>
<p>그래서 다시 찾아봤다.</p>
<p><strong>Location.reverseGeocodeAsync()</strong>
<img src="https://velog.velcdn.com/images/hotteok_/post/f5a83dbf-bd02-40dc-a4c7-864118f6bd85/image.png" alt=""></p>
<p>Geocoding web api를 더 이상 지원하지 않는단다;; 좀 제대로 읽어볼 걸.. <code>Place Autocomplete</code>를 대신 쓰라는데 일단 들어가봄</p>
<blockquote>
<p>Place Autocomplete 서비스는 장소를 반환하는 웹 서비스입니다. HTTP 요청에 대한 응답으로 요청은 검색 문자열과 선택적 지리적 경계가 있습니다. 이 서비스는 텍스트 기반 지역 검색을 위한 자동 완성 기능을 제공합니다. 업체, 주소 및 관심 장소 같은 장소를 확인할 수 있다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/hotteok_/post/2db22889-3a09-4de4-a3ec-be1dd1349add/image.png" alt=""></p>
<p>꼭 필요한 파라미터 값이  <code>input</code> -&gt; 텍스트 스트링을 받는다. 그런데 우리는 받아 넘길 값이 위도 경도 숫자다.</p>
<p>물론 <code>Place API</code>를 활용할 일이 있어 보인다. 매우 유용해 보인다. 장소 세부 정보 및 상소 사진, 주변 지역도 검색 가능하고, 후에 해당 API를 활용할 토이플젝도 해보고 싶다. (딱 기다려..)</p>
<p>아무튼 그래서 찾은게 <a href="https://developers.google.com/maps/documentation/geocoding/requests-reverse-geocoding?hl=ko">역지오코딩(Reverse geocoding)</a> 가보자고.</p>
<p><img src="https://velog.velcdn.com/images/hotteok_/post/f8990562-e7d0-4e19-bfc4-67b05625d404/image.png" alt=""></p>
<blockquote>
<p>요약하자면 사람이 읽을 수 있는 지도 주소로 변환해 준다. 필요한 파라미터도 latlng, key</p>
</blockquote>
<p>내가 원하던거다..!
<br><br><br></p>
<h2 id="🌏-역지오코딩reverse-geocoding-써보자">🌏 역지오코딩(Reverse geocoding) 써보자</h2>
<h3 id="1-키-발급">1. 키 발급</h3>
<p><a href="https://developers.google.com/maps/documentation/geocoding/requests-reverse-geocoding?hl=ko">역지오코딩(Reverse geocoding) 공식문서 링크</a></p>
<p><img src="https://velog.velcdn.com/images/hotteok_/post/4a6d7d5a-50c3-4f08-bbad-7e4d462826c1/image.png" alt=""></p>
<p>공식 문서 링크로 들어가면 상단에 시작하기 버튼 눌러 들어가 api를 발급하자 그래야지 key 파라미터로 전달해 api를 호출할 수 있다. </p>
<p><br><br></p>
<h3 id="2-써보자">2. 써보자</h3>
<p><strong>1) 요청 base Url</strong></p>
<pre><code>//json형태 응답
https://maps.googleapis.com/maps/api/geocode/json

//xml형태 응답
https://maps.googleapis.com/maps/api/geocode/xml
</code></pre><p><strong>2) parameters</strong></p>
<p><strong>필수 옵션</strong></p>
<ul>
<li><p><code>latlng</code> :위도 및 경도 가장 가까운 위치를 지정하는 좌표</p>
<pre><code>ex)latlng=위도(latitude),경도(longitude) 
        -&gt;  `,`(콤마)로 구분</code></pre></li>
<li><p><code>key</code> : 발급받은 내 key</p>
</li>
</ul>
<p><strong>선택적 옵션</strong></p>
<ul>
<li><p><code>language</code> : 결과 반환 언어
  <a href="https://developers.google.com/maps/faq?hl=ko&amp;_gl=1*8eyjao*_up*MQ..*_ga*MTUwNTg2MjEzLjE3MjQ5MjMzNTM.*_ga_NRWSTWS78N*MTcyNDkyMzM1My4xLjAuMTcyNDkyMzM1My4wLjAuMA..#languagesupport">지원되는 언어</a> 참고! 
  한국 - ko
  영어 - en</p>
</li>
<li><p><code>region</code> : ccTLD로 지정된 지역 코드</p>
<details>
<summary>ccTLD...? 뭔데..? </summary>
<div>

<p>국제적으로 나라 또는 특정 지역 그리고 국제 단체 등을 나타내는 인터넷의 도메인 이름에 배당한 고유 부호</p>
<p>  feat.위키피디아
  <a href="https://ko.wikipedia.org/wiki/국가_코드_최상위_도메인#도메인_목록" target="_blank">코드가 궁금하다면 클릭</a></p>
</div>
</details>
</li>
<li><p><code>result_type</code> : 하나 이상의 주소 유형 필터입니다. 파이프 (|)로 구분 -&gt;검색 후 필터 역할 (아니면 전부 다 불러와서 쓸데없이 불러 오는 데이터의 크기가 커진다..)</p>
<ul>
<li><p><code>street_address</code> 는 정확한 상세 주소를 나타냅니다.</p>
</li>
<li><p><code>route</code> 는 이름이 지정된 경로(예: &#39;US 101&#39;)</p>
</li>
<li><p><code>intersection</code>은 일반적으로 두 주요 도로의 주요 교차로</p>
</li>
<li><p><code>political</code>은 정치적 독립체</p>
</li>
<li><p><code>country</code>는 전국적인 정치적 독립체를 나타내고 일반적으로 지오코더에서 반환하는 순위가 가장 높은 유형</p>
</li>
<li><p><code>administrative_area_level_1</code>은 국가 수준 아래 첫 번째 행정 독립체를 나타냅니다. 미국에서 이 행정 구역 수준은 주입니다. 모든 국가에 이러한 행정 구역 수준이 표시되지는 않습니다. 대부분의 경우 거의 일치하지만 지오코딩 결과는 다양한 신호와 위치 데이터를 기반으로 하기 때문에 이러한 일치가 보장되지는 않음</p>
<ul>
<li>level은 administrative_area_level_1~administrative_area_level_7까지 있음 자세한 부분은 공식 문서 참고</li>
</ul>
</li>
<li><p><code>colloquial_area</code>는 일반적으로 사용되는 독립체의 대체 이름을 나타냅니다.</p>
</li>
<li><p><code>locality</code>는 도시 또는 마을로 통합된 정치적 독립체를 나타냅니다.
sublocality는 지역 아래 첫 번째 행정 독립체를 나타냅니다.</p>
</li>
</ul>
</li>
</ul>
<p>** 그 외에도 값이 많으니 필요한건 공식문서를 참고!**</p>
<p><strong>3) 코드 수정</strong></p>
<p>불러오는 응답 값의 구조를 보면 (값은 보기 편하게 삭제했다) 원하는 데이터는 <code>results</code>에 담기며 그 배열의 첫 번째 요소인 <code>address_components</code>의 첫 번째 요소 <code>long_name</code>이 내가 원하는 값이다</p>
<pre><code class="language-json">
{
    &quot;plus_code&quot;: {
        &quot;compound_code&quot;,
        &quot;global_code&quot;
    },
    &quot;results&quot;: [
        {
            &quot;address_components&quot;: [
                {
                    &quot;long_name&quot;,
                    &quot;short_name&quot;,
                    &quot;types&quot;: []
                },
                {
                    &quot;long_name&quot; ,
                    &quot;short_name&quot;,
                    &quot;types&quot;: []
                }
            ],
            &quot;formatted_address&quot;,
            &quot;geometry&quot;,
            &quot;place_id&quot;,
            &quot;types&quot;: []
        }
    ],
    &quot;status&quot;
}</code></pre>
<p>코드 추가</p>
<pre><code class="language-jsx">import { useEffect, useState } from &#39;react&#39;;
import * as Location from &#39;expo-location&#39;;

export default function App() {
  const [location, setLocation] = useState(null);
  const [city, setCity] = useState(&#39;...loading&#39;);
  const [placeId, setPlaceID] = useState(null);
  const [ok, setOk] = useState(false);

  const { status } = await Location.requestForegroundPermissionsAsync();

  if (status !== &#39;granted&#39;) {
    return;
  }

  setOk((prev) =&gt; !prev);

  const {
    coords: { latitude, longitude },
  } = await Location.getCurrentPositionAsync({ accuracy: 5 });

  setLocation({ latitude, longitude });

  //추가

  try {
        const response = await fetch(
      `https://maps.googleapis.com/maps/api/geocode/json?latlng=${latitude},${longitude}&amp;key=${process.env.EXPO_PUBLIC_GOOGLE_MAP_API}&amp;result_type=administrative_area_level_1&amp;language=en`);
     const { results } = await response.json();
     setPlaceID(results[0].place_id);
     setCity(results[0].address_components[0]?.long_name);

  } catch (error) {
     console.error(error);
  }

... 아래 코드 생략
</code></pre>
<p><br><br></p>
<h3 id="추가">추가</h3>
<p>1) Expo 에서 환경변수 사용 방법
    root 경로에 <code>.env</code> 파일 생성 후 <code>EXPO_PUBLIC_[NAME]=VALUE</code> 형태로 생성 후 아래 변수 형태로 불러와 서 쓰면 된다. </p>
<pre><code>process.env.EXPO_PUBLIC_MY_API</code></pre><p>부족한 내용이 있을 수 있으니 더 살펴보고 첨삭해야지...!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[C언어 시작 전 - 진법 변환]]></title>
            <link>https://velog.io/@hotteok_/C%EC%96%B8%EC%96%B4-%EC%8B%9C%EC%9E%91-%EC%A0%84-%EC%A7%84%EB%B2%95-%EB%B3%80%ED%99%98</link>
            <guid>https://velog.io/@hotteok_/C%EC%96%B8%EC%96%B4-%EC%8B%9C%EC%9E%91-%EC%A0%84-%EC%A7%84%EB%B2%95-%EB%B3%80%ED%99%98</guid>
            <pubDate>Thu, 29 Aug 2024 07:22:21 GMT</pubDate>
            <description><![CDATA[<h1 id="🔁-진법-변환">🔁 진법 변환</h1>
<h2 id="1-10진수decimal-number">1. 10진수(decimal number)</h2>
<ul>
<li>일반적인 진법 체계</li>
<li>한 자리 숫자는 10가지(0~9) 존재</li>
<li>자릿수가 올라갈 때마다 $$10^n$$을 곱함</li>
</ul>
<br>


<h2 id="2-2진수bunary-number">2. 2진수(bunary number)</h2>
<ul>
<li>0과 1의 두 가지 숫자로 수를 표현</li>
<li>자릿수가 올라갈 때마다 $$2^n$$을 곱함</li>
</ul>
<br>


<h2 id="3-8진수octal-number">3. 8진수(octal number)</h2>
<ul>
<li>한 자리 숫자 8가지(0~7) 존재</li>
<li>자릿수가 올라갈 때마다 $$8^n$$을 곱함</li>
</ul>
<br>

<h2 id="4-16진수hexadecimal-number">4. 16진수(hexadecimal number)</h2>
<ul>
<li>한 자리 숫자 0<del>9 (10가지 숫자)와 알파벳 A</del>F 총 16개의 존재</li>
<li>자릿수가 올라갈 때마다 $$16^n$$을 곱함</li>
<li>표기가 사용되는 예
  1) 색상표현 (RGB)
  2) 컴퓨터 하드웨어 주소
  3) 메모리에 저장 된 값</li>
<li>C언어에서는 prefix를 붙여 표현 : <code>0x</code>
  ex)
  <code>0xf</code>  16진수 F -&gt; (2진수 : 1111 , 10진수 : 15)
  <code>0x3f</code> 16진수 3F -&gt; 2진수: 111111, 10진수:(3*16+15)</li>
</ul>
<br>


<h2 id="5-2진수16진수-변환">5. 2진수,16진수 변환</h2>
<table>
<thead>
<tr>
<th align="center">2진수(4bit)</th>
<th align="center">16진수</th>
<th align="center">2진수(4bit)</th>
<th align="center">16진수</th>
</tr>
</thead>
<tbody><tr>
<td align="center">0000</td>
<td align="center">0</td>
<td align="center">1010</td>
<td align="center">A(10진수 10)</td>
</tr>
<tr>
<td align="center">0001</td>
<td align="center">1</td>
<td align="center">1011</td>
<td align="center">B(10진수 11)</td>
</tr>
<tr>
<td align="center">0010</td>
<td align="center">2</td>
<td align="center">1100</td>
<td align="center">C(10진수 12)</td>
</tr>
<tr>
<td align="center">0011</td>
<td align="center">3</td>
<td align="center">1101</td>
<td align="center">D(10진수 13)</td>
</tr>
<tr>
<td align="center">0100</td>
<td align="center">4</td>
<td align="center">1110</td>
<td align="center">E(10진수 14)</td>
</tr>
<tr>
<td align="center">0101</td>
<td align="center">5</td>
<td align="center">1111</td>
<td align="center">F(10진수 15)</td>
</tr>
<tr>
<td align="center">0110</td>
<td align="center">6</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">0111</td>
<td align="center">7</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">1000</td>
<td align="center">8</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">1001</td>
<td align="center">9</td>
<td align="center"></td>
<td align="center"></td>
</tr>
</tbody></table>
<ul>
<li>4bit는 16진수 한 자리 숫자</li>
<li>16진수는 0<del>9, A</del>F 까지 한 자리에 씀</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘 문제 해결 패턴(4) - Divide and Conquer]]></title>
            <link>https://velog.io/@hotteok_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%ED%8C%A8%ED%84%B44-Divide-and-Conquer</link>
            <guid>https://velog.io/@hotteok_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%ED%8C%A8%ED%84%B44-Divide-and-Conquer</guid>
            <pubDate>Wed, 28 Aug 2024 09:20:37 GMT</pubDate>
            <description><![CDATA[<h1 id="✔️-4divide-and-conquer분할과-정복">✔️ 4.Divide and Conquer(분할과 정복)</h1>
<ol>
<li>데이터셋을 작은 부분으로 나누고 데이터의 하위집합으로 프로세스를 반복</li>
<li>시간복잡도를 크게 줄일 수 있다</li>
<li>퀵 정렬, 병합 정렬, 이진 탐색</li>
</ol>
<br>
<br>


<h2 id="💻-예제-1">💻 예제 1</h2>
<blockquote>
<p>정렬된 숫자 배열과 검색하려는 숫자를 인자로 받아 해당 위치의 인덱스를 반환하는 함수 search를 작성하시오
(단, 값이 없을 경우 -1을 리턴한다)</p>
</blockquote>
<pre><code>  search([1,2,3,4,5,6],4) // 3
  search([1,2,3,4,5,6],6)  // 5
  search([1,2,3,4,5,6],11) // -1</code></pre><br>
<br>

<h3 id="🔎-내가-했던-풀이">🔎 내가 했던 풀이</h3>
<p><strong>🔸 풀이 전 어떻게 구성할지 생각해봤다</strong></p>
<ol>
<li>배열을 순회하면서 비교 후 검색 할 <code>num</code>과 같으면 해당 인덱스 리턴 없으면 -1리턴</li>
</ol>
<pre><code class="language-javascript">const search = (arr, num) =&gt; {
  for (let i = 0; i &lt; arr.length; i++) {
    if (arr[i] === num) return i;
  }
  return -1;
};</code></pre>
<p><code>O(N)</code>의 시간 복잡도를 가진다. 
    -&gt; 배열에 있는 첫번째 원소부터 n번째 원소까지 하나하나 탐색하므로</p>
<h3 id="🔎-해답">🔎 해답</h3>
<ol>
<li><p>Binary Search 이진탐색
 : 정렬되어 있는 리스트에서 탐색 범위를 절반씩 좁혀가며 데이터를 탐색하는 방법이다. (정렬되어 있지 않으면 쓸 수 없음!)</p>
<p> =&gt; 시간복잡도 <code>log(N)</code>  : 정렬된 배열에서 범위를 반씩 줄여가면서 탐색하기 때문에!</p>
</li>
</ol>
<p><strong>🔸 풀이의 경우 주석으로 내가 이해 한 부분을 작성해봤다.</strong></p>
<pre><code class="language-javascript">const search = (arr, num) =&gt; {
  //서치 할 범위 초기에는 전체로 잡는다
  let min = 0;
  let max = arr.length - 1;

  while (min &lt;= max) {
    let mid = Math.floor((min + max) / 2); //중간 인덱스값을 구한다
    let currentElem = arr[mid];

    if (currentElem &lt; num) {
      min = mid + 1; // 중간 값이 검색 할 num보다 작다? 그 중간값 이전 값은 비교 할 필요 없으므로 min 값(비교군 첫번째 인덱스)에 비교 했던 mid값 다음인 [mid+1 ]을 할당한다
    } else if (currentElem &gt; num) {
      max = mid - 1; // 중간 값이 검색 할 num보다 크다? 그 중간값 이후 부터는 비교 할 필요 없으므로 max값(비교군 마지막 인덱스)에 mid값 이전인 [mid-1]을 할당한다
    } else {
      return mid; //같다면? 해당 인덱스 mid 값을 리턴한다.
    }
  }
  return -1; //없으면 -1리턴
};</code></pre>
<blockquote>
<p>*<em>🤨이진탐색..너란 녀석 나중에 따로 정리해보겠어... *</em></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘 문제 해결 패턴(3) - Sliding Window]]></title>
            <link>https://velog.io/@hotteok_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%ED%8C%A8%ED%84%B43-Sliding-Window</link>
            <guid>https://velog.io/@hotteok_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%ED%8C%A8%ED%84%B43-Sliding-Window</guid>
            <pubDate>Wed, 28 Aug 2024 08:54:22 GMT</pubDate>
            <description><![CDATA[<h1 id="✔️-3-sliding-window">✔️ 3. Sliding Window</h1>
<ol>
<li>한 위치에서 다른 위치로 이동 할 수 있는 window(고정된 사이즈-특정 범위)를 생성, 내부 요소의 값을 이용하는 패턴<ul>
<li>window : 단일 변수, 하위 배열 또는 필요한 경우 다른 문자열도 될 수 있음<ul>
<li>이동은 보통 왼쪽에서 오른쪽, 즉 요소의 시작 위치, 또는 배열이나 문자열의 시작 위치에서 끝나는 위치로 이동</li>
</ul>
</li>
</ul>
</li>
<li>특정 조건에 따라 window는 증가하거나 닫히거나 새로 생성 될 수 있다</li>
<li>배열과 문자열에서 데이터의 하위 집합을 추적하는데 유용함</li>
<li>투 포인터와 비슷한 부분이 있다</li>
</ol>
<br>
<br>
<br>

<h2 id="💻-예제-1">💻 예제 1</h2>
<blockquote>
<p>정수 배열과 n이라는 숫자를 받아
해당 배열에서 n만큼 연속된 요소의 합의 최대값을 계산하는 maxSubArraySum이라는 함수를 작성하시오. </p>
<p>maxSubArraySum([1,2,5,2,8,1,5],2) // 10
maxSubArraySum([1,2,5,2,8,1,5],4) // 17
maxSubArraySum([4,2,1,6],1) //6
maxSubArraySum([4,2,1,6,2],4) // 13
maxSubArraySum([],4) // null</p>
</blockquote>
<br>

<h3 id="🔎-내가-했던-풀이">🔎 내가 했던 풀이</h3>
<p><strong>🔸 풀이 전 어떻게 구성할지 생각해봤다</strong></p>
<ol>
<li>빈 배열 또는 조건에 맞지 않을 경우 <code>null</code>을 리턴한다 -&gt; 배열의 길이보다 n의 숫자가 클때</li>
<li>결과 값으로 쓸 result와 비교를 위해 임시로 비교를 위한 temp 변수 선언</li>
<li><code>temp</code>변수에 첫 비교 값인 n-1 인덱스까지의 값의 합(처음부터 n개 요소의 합) 할당</li>
<li>window는 고정값이므로 한칸씩 이동하므로 이전 첫 요소 빼고 다음 요소 더함 (하나의 인덱스만큼 이동하며 n개의 합을 유지한다) =&gt; 그리고 <code>temp</code> 값과 <code>result</code>를 비교해서 둘 중 큰 숫자를 <code>result</code>에 할당한다.<ul>
<li>for문의 시작은 n부터 시작(배열의 인덱스는 0부터 시작하므로)</li>
<li>배열 모두 비교 후 끝나면 비교하며 저장된 가장 큰 합의 값인 <code>result</code>를 할당한다.</li>
</ul>
</li>
</ol>
<pre><code class="language-javascript">const maxSubarraySum = (arr, n) =&gt; {
  if (arr.length &lt; n) return null;

  let result = 0;
  let temp = 0;

  for (let i = 0; i &lt; n; i++) { 
    result += arr[i];
  }

  temp = result;

  for (let j = n; j &lt; arr.length; j++) {
    temp = temp - arr[j - n] + arr[j];
    result = Math.max(result, temp);
  }

  return result;
};
</code></pre>
<h3 id="🔎-해답">🔎 해답</h3>
<p><strong>위 풀이와 동일 시간 복잡도는 <code>O(N)</code></strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘 문제 해결 패턴(2) - Multiple Pointers]]></title>
            <link>https://velog.io/@hotteok_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%ED%8C%A8%ED%84%B4-Multiple-Pointers2</link>
            <guid>https://velog.io/@hotteok_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%ED%8C%A8%ED%84%B4-Multiple-Pointers2</guid>
            <pubDate>Wed, 28 Aug 2024 08:39:32 GMT</pubDate>
            <description><![CDATA[<h1 id="✔️-2-multiple-pointers">✔️ 2. Multiple Pointers</h1>
<ol>
<li>인덱스 또는 위치 해당하는 포인터와 값을 생성하고 특정 조건 기준으로 처음 끝 중간으로 이동.
 -&gt; 공간 복잡성을 최소화하면서 문제를 해결하는데 효율적</li>
<li>한 쌍의 값이나 조건을 충족시키는 것을 찾는 방식 (보통은 한 쌍을 찾는데 사용)</li>
<li>두 개의 포인터를 생성
 -&gt; 투 포인터라고도 부름</li>
</ol>
<br>
<br>

<h2 id="💻-예제-1">💻 예제 1</h2>
<blockquote>
<p>정렬된 정수의 배열를 받아 합이 0이 되는 한쌍의 숫자를 배열 형태로 리턴하는 sumZero 함수를 작성하시오. 
(합이 0인 한 쌍이 존재하지 않으면 undefined 리턴)</p>
<p>sumZero([-3,-2,-1,0,1,2,3]) // [-3,-3]
sumZero([-2,0,1,3]) // undefined
sumZero([1,2,3]) // undefined</p>
</blockquote>
<br>

<h3 id="🔎-내가-했던-풀이">🔎 내가 했던 풀이</h3>
<p><strong><span style="font-size:18px;">🔸 풀이 전 어떻게 구성할지 생각해봤다</span></strong></p>
<ol>
<li>다중포인터 -&gt; 한쌍의 값을 찾으므로 포인터를 두 개 사용 한다?</li>
<li>처음 끝 양쪽에서부터 이동하며 비교<ul>
<li>합이 0 이면 한쌍의 배열 리턴</li>
<li>합이 양수 끝 포인터 -- (오른쪽 양수가 더 크니까)</li>
<li>합이 음수 시작 포인터 ++ (왼쪽 음수가 더 크니까)</li>
<li>끝 포인터 - 시작 포인터 =&gt; 음수라면 비교 끝 return</li>
</ul>
</li>
</ol>
<br>

<p><strong><span style="font-size:18px;">🔸 위의 내용을 코드로 구성해보면</span></strong></p>
<pre><code class="language-javascript">const sumZero = (intArr) =&gt; {


  let left = 0; //첨
  let right = intArr.length - 1; //끝
  while (left &lt; right) {
    const sum = intArr[left] + intArr[right];
    if (sum === 0) return [intArr[left], intArr[right]];
    else if (sum &gt; 0) right--;
    else left++;
  }
};</code></pre>
<p> <code>시간 복잡도 O(N), 공간 복잡도 O(1)</code> =&gt; 해답도 내가 했던 풀이와 동일했다 🤓</p>
 <br>
 <br>

<p>시간 복잡도를 생각하지 않고 <code>nested loop</code>를 사용한 코드는 어떤걸까? 아래와 같다! </p>
<p>아래의 코드의 성능의 경우 <code>시간복잡도 O(n^2) , 공간 복잡도 O(1)</code>와 같다.</p>
<pre><code class="language-javascript">const sumZeroUseNL = (intArr) =&gt; {
  for (let i = 0; i &lt; intArr.length; i++) {
    for (let j = j + 1; j &lt; intArr.length; j++) {
      if (intArr[i] + intArr[j] === 0) {
        return [intArr[i], intArr[j]];
      }
    }
  }
};</code></pre>
<h3 id="🔎-풀이">🔎 풀이</h3>
<p>내가 했던 풀이와 동일~!</p>
<br>
<br>

<h2 id="💻-예제-2">💻 예제 2</h2>
<blockquote>
<p>정렬된 정수의 배열을 받아 배열의 고유값의 갯수를 리턴하는 countUniqueValues 함수를 작성하시오
(음수가 올 수 있다, 배열은 항상 sort된 상태이다)</p>
<p>countUniqueValues([1,1,1,1,1,2])//2
countUniqueValues([1,2,3,4,4,4,5,5,12,12,13]) //7
countUniqueValues([])//0
countUniqueValues([-2,-1,-1,0,1]) //3</p>
</blockquote>
<br>


<h3 id="🔎-내가-했던-풀이-1">🔎 내가 했던 풀이</h3>
<p><strong><span style="font-size:18px;">🔸 풀이 전 어떻게 구성할지 생각해봤다</span></strong></p>
<ul>
<li>음수가 배열의 요소로 올 수 있음 -&gt; ex)  <code>[-1,1]</code> =&gt; -1과 1 고유값 2가지<ul>
<li>포인터 2개 선언</li>
<li>두개의 포인터를 증가 시키면서 서로 비교,</li>
<li>선증가된 비교값의 포인터가 배열의 마지막 인덱스가 되면 종료 후 갯수 반환</li>
<li>빈 배열을 받으면 무조건 0 리턴 =&gt; 따라서 count의 초기값은 1</li>
</ul>
</li>
</ul>
<p> <span style="font-size:14px;color:gray">처음에 음수를 고려하지 않는 절대값을 비교하는 줄 알고 삽질했었다.. 해당 문제의 의도를 다시 잘 파악해보자...ㅋ..😩</span></p>
<br>

<p><strong><span style="font-size:18px;">🔸 위의 내용을 코드로 구성해보면</span></strong></p>
<pre><code class="language-javascript">const countUniqueValues = (intArr) =&gt; {

  if (intArr.length === 0) return 0;

  let basis = 0;
  let round = 1;
  let count = 1;

  while (round &lt; intArr.length) {
    const baseElem = intArr[basis];
    const roundElem = intArr[round];

    if (baseElem !== roundElem) count++;

    basis++;
    round++;
  }

  return count;
};</code></pre>
<br>
<br>

<h3 id="🔎-풀이-1">🔎 풀이</h3>
<p><strong>while을 사용한 풀이 =&gt; 알고리즘 풀이 과정만 보고 다시 구성해 봄!</strong></p>
<pre><code class="language-javascript">
const solCountuniqueValues = (intArr) =&gt; {
  if (intArr.length === 0) return 0; // 빈 배열은 비교 할 필요 없으니 바로 0 리턴

  let basis = 0;
  let round = 1;

  while (round &lt; intArr.length) {

    if (intArr[basis] !== intArr[round]) {
      basis++;
      intArr[basis] = intArr[round];
    }

    round++;
  }

  return basis + 1;
};</code></pre>
<p><strong>1)변수선언</strong>
basis : 기준점 
round : index를 증가시키며 비교하는 값
<strong>2)과정</strong>
basis와 round 위치의 같으면 round 인덱스 증가
basis와 round 위치의 값이 다르면 basis 인덱스 증가 후 해당 자리에 비교값 할당, round 인덱스 증가 
<strong>3)리턴값</strong>
해당 작업 반복 후 round의 인덱스가 배열 마지막 인덱스가 되면 basis 의 index+1(인덱스는 0부터 시작하므로) 리턴</p>
<br>

<p>위의 내용을 <code>for loop</code>를 이용해 다시 리팩토링😎</p>
<ul>
<li>불필요한 변수 할당 줄이기 , 필요한 변수 1개만 선언</li>
</ul>
<pre><code class="language-javascript">//풀이

const solCountuniqueValues = (intArr) =&gt; {
  if (intArr.length === 0) return 0; // 빈 배열은 비교 할 필요 없으니 바로 0 리턴
  let i = 0;
  for (let j = 0; j &lt; intArr.length; j++) {
      if(intArr[i] !== intArr[j]) {
      i++;
      intArr[i] = intArr[j];
      }
  }

  return i + 1;
};
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘 문제 해결 패턴(1)- Frequency Counter]]></title>
            <link>https://velog.io/@hotteok_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%ED%8C%A8%ED%84%B41</link>
            <guid>https://velog.io/@hotteok_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%ED%8C%A8%ED%84%B41</guid>
            <pubDate>Tue, 27 Aug 2024 04:42:21 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-해결-패턴">문제 해결 패턴</h1>
<blockquote>
<ol>
<li>Frequency Counter </li>
<li>Multiple Pointers</li>
<li>Sliding Window </li>
<li>Divide and Conquer</li>
<li>Dynamic Programming</li>
<li>Greedy Algorithms</li>
<li>Backtracking
등등...</li>
</ol>
</blockquote>
<br>
<br>
<br>

<h2 id="✔️-1-frequency-counter">✔️ 1. Frequency Counter</h2>
<ol>
<li>object 또는 data set를 이용해서 다양한 값과 빈도를 수집</li>
<li>서로 비슷한 값으로 구성 되어 있는지, 
서로 간의 애너그램(서로 같은 철자로 구성된건지),
값이 다른 값이 포함되는지 여부,
두 개 이상 또는 특정하게 발생하는 빈도 확인</li>
<li>배열과 문자열의 중첩 루프 또는 O(N^2) 연산을 대신할 수 있음</li>
</ol>
<br>

<h3 id="💻-예제-1">💻 예제 1</h3>
<blockquote>
<p>두 배열을 받아 , 요소의 갯수가 같으면서 두번째 인자의 배열이 첫번째 인자의 배열의 제곱의 값을 갖고 있는 함수 same을 작성하시오.
 (단, 순서는 상관 없다.)</p>
<p>same([1,2,3],[4,1,9]); // true
same([1,2,3],[1,9]); // false
same([1,2,1],[4,4,1]); // false (must be same frequency)</p>
</blockquote>
<br>
<br>


<h4 id="span-stylefont-size-22pxfont-weightbold🔎-내가-했던-풀이span"><span style="font-size: 22px;font-weight:bold">🔎 내가 했던 풀이</span></h4>
<pre><code class="language-javascript">const same = (arr1, arr2) =&gt; {
  // 배열의 크기가 같지 않으면 비교 할 필요 없이 return false
  if (arr1.length !== arr2.length) return false;
  // arr1 배열 순회
  for (const arr1Elem of arr1) {
    //arr1 요소의 인덱스
    const idx = arr2.indexOf(Math.pow(arr1Elem, 2));
    if (idx &gt; -1) {
      // 인덱스가 있으면 arr2에서 제거해서 중복으로 확인 되는 것 방지
      arr2.splice(idx, 1);
    } else {
      //없으면 바로 false 리턴
      return false;
    }
  }
  return true; //모든 조건 만족하면 true
  //
};


//문제 예제의 케이스의 답은 만족 하므로 큰 배열의 값으로 한번 더 테스트
const t1 = performance.now();
console.log(
  same(
    [
      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1, 2,
      3, 4, 5, 6, 7, 8, 9, 10, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100,
    ],
    [
      1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 10000, 1, 4, 9, 16, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 10000, 25, 36, 49,
      64, 81, 100, 10000, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 10000,
    ]
  )
);
const t2 = performance.now();
console.log(`same 걸린 시간 : ${(t2 - t1) / 1000}s`);
//same 걸린 시간 : 0.010898541000000008s</code></pre>
<p>뭔가 문제 없이 잘 돌아간다. 뭔가 중첩 루프도 없어보였다.</p>
<p><span style="color:#f56942 ;font-weight:bold">하지만..</span> 위의 해결책의 경우 하나의 for문을 사용한 것 같지만 그 자체가 loop인 indexOf를 사용했다.</p>
<p>게다가 배열의 splice 메서드 또한 요소가 마지막에 있다면 constant time인 <strong><code>O(1)</code></strong>의 시간 복잡도를 가지지만, 요소가 중간이나 앞에 있다면 linear time <strong><code>O(n)</code></strong> 의 시간 복잡도를 가진다.</p>
<blockquote>
<p>위의 해답은 <span style="color:#f56942;font-weight:bold">시간복잡도 = O(N^2)의 복잡도를 가지게 된다...</span></p>
</blockquote>
<br>
<br>

<h4 id="span-stylefont-size-22pxfont-weightbold🔎-frequency-conter-이용한-답--시간복잡도-onspan"><span style="font-size: 22px;font-weight:bold">🔎 Frequency Conter 이용한 답 =&gt; 시간복잡도 O(n)</span></h4>
<ul>
<li>두 개의 중첩 루프보다 개별 루프가 낫다</li>
</ul>
<blockquote>
<p> ** 객체를 사용 **
    : 객체를 사용하여 구성하는 것은 배열이나 문자열의 내용을 분석하는 방법으로 두 개의 배열을 객체로 세분화 하여 각 배열의 요소들 분류 후 각 배열을 비교 가능하다</p>
</blockquote>
<pre><code class="language-javascript">
const same = (arr1, arr2) =&gt; {
  if (arr1.length !== arr2.length) return false;
  // 중첩 for루프 없이 개별 배열의 빈도수를 count
  const frequencyCounter1 = {};
  const frequencyCounter2 = {};
  for (const val of arr1) {
    frequencyCounter1[val] = (frequencyCounter1[val] || 0) + 1;
  }
  for (const val of arr2) {
    frequencyCounter2[val] = (frequencyCounter2[val] || 0) + 1;
  }
  for (const key in frequencyCounter1) { 
    // 객체의 키로 접근하는 것은 O(1)의 시간 복잡도를 가진다!
    // 제곱이 되는 값이 있는지 먼저 확인
    if (!(key ** 2 in frequencyCounter2)) return false;

    //제곱의 값이 있다면 서로 그 갯수가 동일한지 확인
    if (frequencyCounter2[key ** 2] !== frequencyCounter1[key]) return false;
  }

  return true;
};

const t3 = performance.now();
console.log(
  same(
    [
      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1, 2,
      3, 4, 5, 6, 7, 8, 9, 10, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100,
    ],
    [
      1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 10000, 1, 4, 9, 16, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 10000, 25, 36, 49,
      64, 81, 100, 10000, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 10000,
    ]
  )
);
const t4 = performance.now();
console.log(`same 걸린 시간 : ${(t4 - t3) / 1000}s`); 
//same 걸린 시간 : 0.000051708000000004974s</code></pre>
<p>객체는 순서 없는 데이터 집합으로 key값으로 접근한다 따라서 키를 통해 값에 접근 하는 것은 O(1)의 시간을 가지므로 배열을 순회하는 것 보다 더 시간이 적다.</p>
<p>수행시간 비교하면 내가 했던 방식은 <code>약 0.0108985s</code> 
frequency counter 사용 시 <code>약 0.0.0000517s</code> 입력 값의 배열의 크기가 클 수록 시간 차이가 컸다.</p>
<br>
<br>
<br>

<h3 id="💻-예제-2">💻 예제 2</h3>
<blockquote>
<p>두 개의 문자열을 받아 서로의 애너그램인지 확인 후 true/false 리턴하는 함수 validAnagram을 작성하시오</p>
<p>validAnagram(&#39;&#39;,&#39;&#39;); // true
validAnagram(&#39;aaz&#39;,&#39;zza&#39;); // false
validAnagram(&#39;anagram&#39;,&#39;nagaram&#39;); //true
validAnagram(&#39;rat&#39;,&#39;car&#39;); //false
validAnagram(&#39;awesome&#39;,&#39;awesom&#39;); //false
validAnagram(&#39;qwerty&#39;,&#39;qeywrt&#39;); //true
validAnagram(&#39;texttwisttime&#39;,&#39;timetwisttext&#39;); //true</p>
</blockquote>
<br>
<br>

<h4 id="span-stylefont-size-22pxfont-weightbold🔎-내가-했던-풀이span-1"><span style="font-size: 22px;font-weight:bold">🔎 내가 했던 풀이</span></h4>
<pre><code class="language-javascript">const validAnagram = (str1, str2) =&gt; {
  //문자열의 길이가 다르다면 비교 할 필요 없이 false 리턴
  if (str1.length !== str2.length) return false;
  // 빈문자열끼리는 true
  if (str1 === &#39;&#39; &amp;&amp; str2 === &#39;&#39;) return true;

  const str1Counter = {};
  const str2Counter = {};

  //각각 str1과 str2의 문자열 안의 글자 수의 빈도수를 각각의 object에 할당
  for (const char of str1) {
    str1Counter[char] = (str1Counter[char] || 0) + 1;
  }
  for (const char of str2) {
    str2Counter[char] = (str2Counter[char] || 0) + 1;
  }

  // 서로 객체 키가 다르면 서로의 애너그램이 될 수 없으므로 false 리턴
  for (const char in str1Counter) {
    if (str1Counter[char] !== str2Counter[char]) {
      return false;
    }
  }
  return true;
};</code></pre>
<p>중첩 루프를 사용하지 않으면서 시간 복잡도 O(n)의 방식으로 해결 했다. 하지만 리팩토링 필요</p>
<ul>
<li>count를 위한 obejct 하나만 선언</li>
<li>해당 char이 존재하는 지 확인, 만약 이미 count 된 경우는 -1 
  : 갯수가 같다면 0이 된다 그 이후 동일 문자가 있다면 <code>if (!strCounter[char])</code> 에서 0값, 즉 true가 되므로 false리턴하게된다 </li>
</ul>
<pre><code class="language-javascript">
const validAnagramRefact = (str1, str2) =&gt; {
  if (str1.length !== str2.length) return false;
  if (str1 === &#39;&#39; &amp;&amp; str2 === &#39;&#39;) return true;
  const strCounter = {};
  for (const char of str1) {
    strCounter[char] ? (strCounter[char] += 1) : (strCounter[char] = 1);
  }
  for (const char of str2) {
    if (!strCounter[char]) {
      return false;
    } else {
      strCounter[char] -= 1;
    }
  }
  return true;
};</code></pre>
<p>후자의 코드가 불필요한 object 추가 선언 없이 더 깔끔해 보인다.🤓</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘 문제 해결 접근법]]></title>
            <link>https://velog.io/@hotteok_/%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%EC%A0%91%EA%B7%BC%EB%B2%95</link>
            <guid>https://velog.io/@hotteok_/%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%EC%A0%91%EA%B7%BC%EB%B2%95</guid>
            <pubDate>Tue, 27 Aug 2024 03:18:11 GMT</pubDate>
            <description><![CDATA[<h1 id="알고리즘-algorithm">알고리즘 (algorithm)</h1>
<blockquote>
<p>문제 해결 방법을 정의한 &#39;일련의 단계적 절차&#39;이자 어떠한 문제를 해결하기 위한 &#39;동작들의 모임&#39;이다
출처 : wiki</p>
</blockquote>
<p>즉, 문제 해결 위해 수행해야 하는 일련의 과정 및 단계</p>
<br>
<br>

<h2 id="🧐-어떻게-접근해야-할까">🧐 어떻게 접근해야 할까?</h2>
<ol>
<li>문제 해결을 위한 계획 수립</li>
<li>일반적 문제 해결 패턴 파악</li>
</ol>
<br>


<h2 id="🔎-문제-해결-단계">🔎 문제 해결 단계</h2>
<blockquote>
<p>EX) 
문자열을 받아 각각의 문자의 갯수를 출력하는 charCount 함수를 작성하시오 
(단, 대소문자 구분 없음)</p>
</blockquote>
<br>



<h3 id="1️⃣step-01---문제-이해">1️⃣STEP 01 - 문제 이해</h3>
<ol>
<li>자신만의 방식으로 바꿔서 이해 가능한가?</li>
<li>그 문제의 입력값(input)이 무엇인가? 
 -&gt;입력값의 형태 등등</li>
<li>문제 해결을 위한 결과(output)는 무엇인가? 
 -&gt; 출력 값의 형태 등등</li>
<li>입력값이 출력값을 결정할 수 있는가?
 -&gt;문제 해결을 위한 충분한 정보를 알고,갖고 있는가?</li>
<li>문제의 중요한 부분이 무엇인지 아는가? 해당 부분을 어떻게 명칭하는가?</li>
</ol>
<br>



<h3 id="2️⃣step-02---구체적인-예시">2️⃣STEP 02 - 구체적인 예시</h3>
<ol>
<li>간단한 예제로 시작 해서 복잡한 예제로</li>
<li>빈 입력값 
 -&gt; 유효하지 않는 입력값이 주어진 상황 유용</li>
<li>유효하지 않은 입력값</li>
</ol>
<pre><code class="language-javascript">charCount(&#39;aaaA&#39;); // {a:4}
charCount(&#39;Hi~ Hello World! 1223&#39;);
/*
{
  h: 2,
  i: 1,
  e: 1,
  l: 3,
  o: 2,
  w: 1,
  r: 1,
  d: 1,
  1: 1,
  2: 2,
  3: 1
}
*/</code></pre>
<br>



<h3 id="3️⃣step-03---문제의-세분화">3️⃣STEP 03 - 문제의 세분화</h3>
<ol>
<li>기본적 구성요소 작성 
➡️ 감이 잘 잡히지 않거나 이해되지 않는 부분들을 파악하는 데 도움이 된다</li>
</ol>
<pre><code class="language-javascript">const charCount = (str) =&gt; { // 기본적 구성 요소
  // 실행 과정
  // 리턴 : 객체, 각각의 키는 소문자, 값은 숫자, 특수문자 공백 제외
}</code></pre>
<pre><code class="language-javascript">function charCount (str)  { // 세분화
   [시작] =&gt; 객체 생성
   [과정] =&gt; 
       string 문자열 순회하며 각각의 문자 처리
       문자가 숫자/문자 &amp;&amp; 객체 안에 없을 경우 =&gt; object의 key로 설정 후 +1
       문자가 숫자/문자 &amp;&amp; 객체 안에 있을 경우 =&gt; 해당 숫자/문자의 key로 값을 찾아 +1
       문자나 숫자가 아닌 공백,마침표 등등 일 경우 카운팅 하지 않는다
   [끝] =&gt; 객체를 반환한다
};</code></pre>
<br>




<h3 id="4️⃣step-04---해결--단순화">4️⃣STEP 04 - 해결 / 단순화</h3>
<ol>
<li>이전 일련의 과정을 통해 문제 해결</li>
<li>당장 해결하지 못한다면 단순화 부터 
 ➡️ 다른 문제 해결을 위해 시간이 많이 소요되는 부분을 배제하여 단순화 시킴
 ➡️ 문제를 단순화 하는 과정(동작 방식의 이해)에서 문제의 어려운 부분을 파악하면서 다시 통합</li>
</ol>
<pre><code class="language-javascript">

function charCount(str) {
  // 시작 =&gt; 객체 생성
  const result = {};
  // 과정 =&gt; string 문자열 순회하며 각각의 문자 처리
  for (let i = 0; i &lt; str.length; i++) {
    // 영대문자 -&gt; 영소문자
    const char = str[i].toLowerCase();

    // 문자나 숫자가 아닌 공백,마침표 등등 일 경우 카운팅 하지 않고 다음 문자열 체크
    if (/[`~!@#$%^&amp;*()_|+\-=?;:&#39;&quot;,.&lt;&gt;\{\}\[\]\\\/ ]/gim.test(char)) continue;

    if (result[char] &gt; 0) { // 문자가 숫자/문자 &amp;&amp; 객체 안에 없을 경우 =&gt; object의 key로 설정 후 +1
      result[char]++;
    } else { //문자가 숫자/문자 &amp;&amp; 객체 안에 있을 경우 =&gt; 해당 숫자/문자의 key로 값을 찾아 +1

      result[char] = 1;
    }
  }
  // 끝 =&gt; 객체를 반환한다
  return result;
}


console.log(charCount(&#39;aaaaa~~~~bbb**(@@ccccccccccc!!!!&amp;&amp;&amp;    dddddd&#39;));  //{ a: 5, b: 3, c: 11, d: 6 }
</code></pre>
<br>


<h3 id="5️⃣step-05---검증-및-재구성리팩토링">5️⃣STEP 05 - 검증 및 재구성(리팩토링)</h3>
<ol>
<li>결과 확인했는가?</li>
<li>결과를 다른 방식으로 도출 할 수 있는가?</li>
<li>한눈에 알아보고 이해할 수 있는가?</li>
<li>해결책을 다른 문제에 적용할 수 있는가?</li>
<li>해결책의 성능을 향상할 수 있는가? 
 ➡️ 해결책을 도출하면서 가장 먼저 고려할 부분</li>
<li>다른방식으로 리팩토링 할 방법을 고려할 수 있는 가?</li>
<li>다른 사람들은 어떻게 해결했는가? 
 ➡️ 새로운 접근 방식과 다른 해결책을 알 수 있음</li>
</ol>
<p><code>💡 예제 풀이에서 선택했던 정규표현식은 일반적으로 백트래킹으로 일치 여부 판단 , 최악의 경우 O(2^n)의 복잡도를 가짐 (n=정규식 크기)
 -&gt; 어디까지나 최악의 경우, 까다로운 조건이 아니라면 큰 문제는 없으나 성능 향상을 위해 아래와 같이 시간복잡도 O(1)방식으로 변경 가능</code></p>
<pre><code class="language-javascript">function isCharNumeric(char) {
  const code = char.charCodeAt(0);
  if (
    !(code &gt; 47 &amp;&amp; code &lt; 58) &amp;&amp; // numeric (0 to 9)
    !(code &gt; 64 &amp;&amp; code &lt; 91) &amp;&amp; // upper (A to Z)
    !(code &gt; 96 &amp;&amp; code &lt; 123) // lower (a to z)
  ) {
    return false;
  }
  return true;
}

function charCount(str) {
  // 시작 =&gt; 객체 생성
  const result = {};
  // 과정 =&gt; string 문자열 순회하며 각각의 문자 처리
  for (const char of str.toLowerCase()) {
    // 문자나 숫자가 아닌 공백,마침표 등등 일 경우 카운팅 하지 않고 다음 문자열 체크
    if (!isCharNumeric(char)) continue;

    // 문자가 숫자/문자 &amp;&amp; 객체 안에 없을 경우 =&gt; object의 key로 설정 후 +1
    //문자가 숫자/문자 &amp;&amp; 객체 안에 있을 경우 =&gt; 해당 숫자/문자의 key로 값을 찾아 +1
    result[char] = ++result[char] || 1;
  }
  // 끝 =&gt; 객체를 반환한다
  return result;
}

console.log(charCount(&#39;aaaaa~~~~bbb**(@@ccccccccccc!!!!&amp;&amp;&amp;    dddddd&#39;)); //{ a: 5, b: 3, c: 11, d: 6 }</code></pre>
<br>

<hr>
<br>


<p>🥲그전에는 무작정 아무것도 고려하지 않고 결과만 나오는 것에만 집중해 코드부터 냅다 썼는데... 확실히 위의 방법대로 따라가니 머릿속에 더 정리되고 구현 시간이 조금 줄어든 느낌이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[C언어 시작 전]]></title>
            <link>https://velog.io/@hotteok_/C%EC%96%B8%EC%96%B4-%EC%8B%9C%EC%9E%91-%EC%A0%84</link>
            <guid>https://velog.io/@hotteok_/C%EC%96%B8%EC%96%B4-%EC%8B%9C%EC%9E%91-%EC%A0%84</guid>
            <pubDate>Mon, 26 Aug 2024 05:38:32 GMT</pubDate>
            <description><![CDATA[<h2 id="컴퓨터와-2진법">컴퓨터와 2진법</h2>
<blockquote>
<p>컴퓨터는 디지털 장치 0과 1로 표기 ➡️ 2진법 체계</p>
</blockquote>
<ol>
<li>1bit ➡️ 전기 스위치 1개<ul>
<li>경우의 수 2가지
: 스위치가 On 상태 = 1 , 흐르지 않는 Off 상태 = 0</li>
</ul>
</li>
</ol>
<ol start="2">
<li>4bit 여러 스위치(or 전선) 4개씩 묶으면 ➡️  2^4 16개의 경우의 수를 가짐<ul>
<li>따라서, 4bit 씩 묶었을 경우 16진수 체계로 사용함</li>
</ul>
</li>
</ol>
<h2 id="게이트-회로">게이트 회로</h2>
<p><img src="https://velog.velcdn.com/images/hotteok_/post/c20a8084-83bf-4952-959c-b1e78a2f222f/image.jpg" alt=""></p>
<ul>
<li>게이트 : 게이트는 논리회로의 기본 하드웨어 기본요소이며, 입력 논리의 필요 조건을 만족할 때 1 또는 0의 신호를 출력</li>
</ul>
<ol>
<li>AND(논리곱) 연산 : 둘 다 참이 참</li>
<li>OR(논리합) 연산: 둘 중 하나라도 참이면 참</li>
<li>XOR(exclusive or - 배타적 논리합) 연산 : 입력이 서로 다르면 참</li>
<li>NOT(논리부정) : 거짓은 참 참은 거짓, Inveter라 부르기도 함</li>
</ol>
<p>=&gt; 가산기 만들때 필요한 개념</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[빅오 표기법(Big O notation)-2]]></title>
            <link>https://velog.io/@hotteok_/%EB%B9%85%EC%98%A4-%ED%91%9C%EA%B8%B0%EB%B2%95Big-O-notation-2</link>
            <guid>https://velog.io/@hotteok_/%EB%B9%85%EC%98%A4-%ED%91%9C%EA%B8%B0%EB%B2%95Big-O-notation-2</guid>
            <pubDate>Fri, 23 Aug 2024 01:08:53 GMT</pubDate>
            <description><![CDATA[<h2 id="object와-big-owithjs">Object와 Big O‹with.js›</h2>
<blockquote>
<p>Object는 순서가 없다(unordered list) 오로지 key🔑를 통해서 접근 및 추가!</p>
<ul>
<li>정렬이 필요 없을 때</li>
<li>빠른 접근,추가,삭제</li>
</ul>
</blockquote>
<h3 id="✔️-object의-추가삭제접근탐색">✔️ Object의 추가,삭제,접근,탐색</h3>
<ol>
<li><p>Insertion(추가) - O(1)</p>
</li>
<li><p>Removal(삭제) - O(1)</p>
</li>
<li><p>Searching(탐색) - O(N) </p>
<ul>
<li>객체의 프로퍼티를 전부 순회해서 값을 확인해야 하기 때문에 linear time O(N)</li>
</ul>
</li>
<li><p>Access(접근) - O(1)</p>
</li>
</ol>
<h3 id="✔️-object-method">✔️ Object Method</h3>
<ol>
<li>Object.keys - O(N)</li>
<li>Object.values - O(N)</li>
<li>Object.entries - O(N)</li>
<li>object.hasOwnProperty(key) , Object.hasOwn(object,key)- O(1)</li>
</ol>
<pre><code class="language-javascript">
const exObject = {
  one : 1,
  two : 2,
  three : 3,
  isTrue : true,
  isFalse : false,
}

// Object의 크기가 커질 수록 method가 처리하는 연산이 커짐 O(N) 
console.log(Object.keys(exObject)); 
// key 배열 return [ &#39;one&#39;, &#39;two&#39;, &#39;three&#39;, &#39;isTrue&#39;, &#39;isFalse&#39; ]

/* Objects.valuse, Object.entires  
또한  Object.keys와 마찬가지인 이유로 object의 요소가 늘어날수록 연산이 커짐 O(N) */
console.log(Object.values(exObject)); 
// value 배열 return [ 1, 2, 3, true, false ]

console.log(Object.entries(exObject)); 
/* [key-value]쌍의 배열
[
  [ &#39;one&#39;, 1 ],
  [ &#39;two&#39;, 2 ],
  [ &#39;three&#39;, 3 ],
  [ &#39;isTrue&#39;, true ],
  [ &#39;isFalse&#39;, false ]
]
*/

/* Object.hasOwnProperty(key) , Object.hasOwn(object,key)
-&gt; object의 내부 key값 존재 유무 정해진 값을 받아 boolean type으로 return =&gt; O(1) */
console.log(exObject.hasOwnProperty(&#39;one&#39;));//true
console.log(exObject.hasOwnProperty(1));//false (key기준)
console.log(Object.hasOwn(exObject,&#39;two&#39;));//true</code></pre>
<h2 id="array와-big-owithjs">Array와 Big O‹with.js›</h2>
<blockquote>
<ul>
<li>ordered list</li>
<li>순서가 정해져 있기 때문에 연산에 시간이 더 걸릴 수 있다.</li>
<li>배열에 있는 데이터를 접근하는 것은 빠름,</li>
<li>정렬될 필요가 있는 데이터 및 정렬 되어 있는 데이터 보관 유리</li>
</ul>
</blockquote>
<h3 id="✔️-array의-추가삭제접근탐색">✔️ Array의 추가,삭제,접근,탐색</h3>
<ol>
<li>Insertion(삽입) <ul>
<li>맨 앞: O(N) =&gt; 요소들이 하나씩 뒤로 밀리며 index 재정렬 필요</li>
<li>맨 뒤: O(1) </li>
</ul>
</li>
<li>Removal(삭제) <ul>
<li>먠 앞, 중간 추가: O(N) =&gt; index 재정렬 필요</li>
<li>맨 뒤: O(1)</li>
</ul>
</li>
<li>Searching(검색) - O(N)</li>
<li>Access(접근) - O(1)</li>
</ol>
<h3 id="✔️-array-method">✔️ Array Method</h3>
<ol>
<li>push , pop - O(1)
: index를 이용하여 접근하는 것과 동일, constant time, 빠름</li>
</ol>
<ol start="2">
<li><p>shift - O(N)
: reindex 필요</p>
</li>
<li><p>unshift - O(N)
: reindex 필요</p>
</li>
<li><p>concat - O(N) 
: 병합 할 배열의 크기가 커질 수록 오래 걸림</p>
</li>
<li><p>slice - O(N)
: 배열 전체 또는 일부를 copy하지만 copy할 배열의 길이에 따라 다름</p>
</li>
</ol>
<ol start="6">
<li><p>splice - O(N)
: elem 제거 및 추가-O(N)</p>
</li>
<li><p>sort - O(N logN)</p>
</li>
<li><p>forEach(),map(),filter(),reduce() 등등 - O(N)</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[빅오 표기법(Big O notation)]]></title>
            <link>https://velog.io/@hotteok_/%EB%B9%85%EC%98%A4-%ED%91%9C%EA%B8%B0%EB%B2%95Big-O-notation</link>
            <guid>https://velog.io/@hotteok_/%EB%B9%85%EC%98%A4-%ED%91%9C%EA%B8%B0%EB%B2%95Big-O-notation</guid>
            <pubDate>Thu, 22 Aug 2024 02:22:48 GMT</pubDate>
            <description><![CDATA[<h2 id="big-o-표기법">Big o 표기법</h2>
<ul>
<li>불필요한 연산을 제거하여 알고리즘의 성능을 평가하기 위해 사용한다.(최악인 경우를 평가)</li>
<li>측정되는 복잡도 시간 복잡도와 공간 복잡도가 있다.</li>
<li>코드가 느려지거나 장애 발생 시 비능률적인 코드를 특정해 애플리케이션의 문제점을 찾는 데 도움이 된다.</li>
</ul>
<h3 id="특징">특징</h3>
<ol>
<li>상수항을 무시한다
 ex) $$O(n+3) =&gt; O(n)$$</li>
<li>계수를 무시한다
 ex) $$O(3n) =&gt; O(n)$$</li>
<li>최고차항만 표기한다
 ex) $$O(3n^2+2n+5) =&gt; O(n^2)$$</li>
</ol>
<h3 id="시간-복잡도">시간 복잡도</h3>
<ul>
<li>프로세스가 수행해야하는 연산을 수치화 한 것
  (시간 기준이 아닌 것은 컴퓨터 하드웨어 성능 및 여러 조건에 의해 조금씩 달라 질 수 있기 때문에)</li>
</ul>
<blockquote>
<p>$$O(1) &lt; O(log N) &lt; O(N) &lt; O(N log N) &lt; O(N^2) &lt; O(N^3) &lt; O(2^n)$$</p>
<p>(우측으로 갈 수록 효율⬇️😞) </p>
</blockquote>
<h3 id="big-o-표기법-종류">Big o 표기법 종류</h3>
<ol>
<li><p>$$O(1)$$ - 상수시간
 : 입력 데이터에 관계 없이 일정
 ex) stack -push/pop</p>
</li>
<li><p>$$O(log N)$$ - 로그 시간
 : 데이터의 로그에 비례해 알고리즘의 단계가 늘어날 때, 알고리즘이 로그 시간으로 실행
 (연산이 한 번 실행될 때 마다 데이터의 크기가 절반 감소, 지수가2)
 ex)이진트리</p>
</li>
<li><p>$$O(N)$$ - 선형 시간
 : 데이터의 크기가 커지는 만큼 같은 비율로 늘어남
 ex)for문</p>
</li>
<li><p>$$O(N logN)$$ - 선형 로그 시간
 :로그 시간 복잡도와 선형 시간 복잡도를 곱한 만큼커짐
 (입력 데이터가 많아질수록 처리 시간이 로그 배만큼 더 늘어남)
 ex)퀵 정렬(Quick Sort),병합 정렬(Merge Sort),힙 정렬(Heap Sort)</p>
</li>
<li><p>$$O(N^2)$$ - 2차시간 , 다항
 :알고리즘의 복잡도는 n의 제곱에 정비례
 ex)삽입 정렬(Insertion Sort), 버블 정렬(Bubble Sort), 선택 정렬(Selection Sort), 이중 for 문</p>
</li>
<li><p>$$O(2^n)$$ - 지수시간
 : 최악의 시간 복잡도로 주로 재귀적으로 수행하는 알고리즘
 ex)피보나치 수열, 재귀가 역기능할 경우</p>
</li>
</ol>
<h3 id="공간-복잡도">공간 복잡도</h3>
<ul>
<li>알고리즘의 실행을 완료할 때까지 필요한 자원의 양 (고정 공간, 데이터 구조 공간, 임시 공간의 메모리)를 얼마나 사용하는지 확인</li>
</ul>
<ul>
<li>Big o 표기법 사용 가능</li>
<li>JS에서    <ul>
<li>$$O(1)$$ =&gt; Booleans, numbers, undefined, null</li>
<li>$$O(n)$$ =&gt; String, array, object</li>
</ul>
</li>
</ul>
<pre><code>
//ex01 =&gt; Number constant space =&gt; O(1)
const sum = (array) =&gt; {
  let total = 0; //number
  for (let i = 0; i &lt; array.length; i++) {
    total += array[i]; // number
  }
  return total;
}; 

//ex02 =&gt; Array 배열이 커질 수록 return되는 new Array 커짐 O(n)

const double = (array) =&gt; {
  let newArr = []; // array 입력 값에 따라 배열의 크기가 커지게됨
  for (let i = 0; i &lt; array.length; i++) {
    newArr.push(array[i]); 
  }
  return newArr; // n numbers
};
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 나누어 떨어지는 숫자 배열]]></title>
            <link>https://velog.io/@hotteok_/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%82%98%EB%88%84%EC%96%B4-%EB%96%A8%EC%96%B4%EC%A7%80%EB%8A%94-%EC%88%AB%EC%9E%90-%EB%B0%B0%EC%97%B4</link>
            <guid>https://velog.io/@hotteok_/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%82%98%EB%88%84%EC%96%B4-%EB%96%A8%EC%96%B4%EC%A7%80%EB%8A%94-%EC%88%AB%EC%9E%90-%EB%B0%B0%EC%97%B4</guid>
            <pubDate>Thu, 20 Apr 2023 03:49:22 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<blockquote>
<p>array의 각 element 중 divisor로 나누어 떨어지는 값을 오름차순으로 정렬한 배열을 반환하는 함수, solution을 작성해주세요.
divisor로 나누어 떨어지는 element가 하나도 없다면 배열에 -1을 담아 반환하세요.</p>
</blockquote>
<h3 id="제한사항">제한사항</h3>
<ul>
<li>arr은 자연수를 담은 배열</li>
<li>정수 <code>i</code>,<code>j</code>에 대해 <code>i ≠ j</code> 이면 <code>arr[i] ≠ arr[j]</code> </li>
<li>divisor은 자연수</li>
<li>array은 1 이상인 배열</li>
</ul>
<h3 id="입출력-예">입출력 예</h3>
<table border=1>
    <thead>
        <tr>
          <th>arr</th>
          <th>divisor</th>
          <th>return</th>
        </tr>
    </thead>
    <tbody>
        <tr>
          <td>[5, 9, 7, 10]</td>
          <td>5</td>
          <td>[5, 10]</td>
        </tr>
        <tr>
          <td>[2, 36, 1, 3]</td>
          <td>1</td>
          <td>[1, 2, 3, 36]</td>
        </tr>
        <tr>
          <td>[3,2,6]</td>
          <td>10</td>
          <td>[-1]</td>
        </tr>
    </tbody>
</table>

<h3 id="나의-풀이">나의 풀이</h3>
<blockquote>
<ol>
<li><code>sort()</code>로 오름차순 정렬</li>
<li><code>배열 요소 % divisor === 0</code>인 조건만 <code>filter()</code></li>
<li><code>answer</code>의 배열의 길이가 0인 경우 <code>[-1]</code> 를 아니면 <code>answer</code> 리턴</li>
</ol>
</blockquote>
<pre><code class="language-javascript">function solution(arr, divisor) {
  const answer = arr.sort((a,b)=&gt;a-b).filter(elem =&gt; elem %divisor === 0)

  return answer.length === 0 ? [-1] : answer
}
</code></pre>
<ul>
<li>해당 풀이로 테스트 6번의 경우 26.56ms가 걸렸다.</li>
</ul>
<blockquote>
<p>테스트 6번에 대한 러닝타임 줄이기</p>
</blockquote>
<pre><code class="language-javascript">
function solution(arr, divisor) {
  const answer = arr.filter(elem =&gt; elem %divisor === 0)

  return answer.length === 0 ? [-1] : answer.sort((a,b)=&gt;a-b)
}
</code></pre>
<ul>
<li><p>조건에 맞는 값을 return할때만 sort실행</p>
</li>
<li><p>테스트 6번 2.21ms (총 24ms 가량 러닝타임 줄어들었다.)</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 약수의 합 ]]></title>
            <link>https://velog.io/@hotteok_/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%95%BD%EC%88%98%EC%9D%98-%ED%95%A9</link>
            <guid>https://velog.io/@hotteok_/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%95%BD%EC%88%98%EC%9D%98-%ED%95%A9</guid>
            <pubDate>Mon, 17 Apr 2023 01:46:13 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p>정수 n을 입력받아 n의 약수를 모두 더한 값을 리턴하는 함수, solution을 완성해주세요.</p>
<h4 id="제한사항">제한사항</h4>
<p><code>n</code>은 0이상 3000이하인 정수입니다.</p>
<h4 id="입출력예">입출력예</h4>
<p><code>n = 12</code> =&gt; return 28
<code>n = 6</code> =&gt; return 6</p>
<h4 id="나의-풀이">나의 풀이</h4>
<ul>
<li><p>약수 : 어떤 수를 나누어떨어지게 하는 수</p>
</li>
<li><p>주어진 숫자의 모든 약수를 구해 더해주는 값으로
% 연산자와 while 반복문 그리고 reduce를 사용하기로 했다.</p>
</li>
</ul>
<blockquote>
<p>나머지가 0인 숫자를 배열에 담는다
해당 배열의 누적 합을 return한다</p>
</blockquote>
<pre><code class="language-javascript">const solution = (n) =&gt; {
    let answer= [];
    let check =1;
    while (check &lt;= n) {

        if(n % check === 0) answer.push(check);
        check ++;
    }
    return answer.reduce((arr,cur) =&gt; arr+cur,0) ;
}</code></pre>
<h4 id="주의할점">주의할점</h4>
<blockquote>
<p>제출 후 런타임 에러 관련 오류</p>
</blockquote>
<p>-n이 0일 경우 빈 배열을 전달하게 되므로 reduce사용 시 initialValue를 0으로 설정해주자</p>
<pre><code>callback의 최초 호출에서 첫 번째 인수에 제공하는 값. 
   초기값을 제공하지 않으면 배열의 첫 번째 요소를 사용합니다. 
빈 배열에서 초기값 없이 reduce()를 호출하면 오류가 발생하는 점 참고.</code></pre><p><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce" target="_blank">mdn reduce() 문서 바로가기</a></p>
<h4 id="다른방법-풀이">다른방법 풀이</h4>
<ul>
<li>굳이 빈 배열 및 나눌 수에 대한 변수 선언없이 푸는 것이 더 깔끔해보인다.</li>
</ul>
<pre><code class="language-javascript">
const solution = (n) =&gt; {
  let sum = 0;
    for (let i = 1; i &lt;= num; i++) {
        if (num % i === 0) sum += i
    }
    return sum
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[호이스팅(Hoisting)]]></title>
            <link>https://velog.io/@hotteok_/%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85Hoisting</link>
            <guid>https://velog.io/@hotteok_/%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85Hoisting</guid>
            <pubDate>Fri, 14 Apr 2023 03:42:14 GMT</pubDate>
            <description><![CDATA[<h3 id="1-호이스팅-hoisting">1. 호이스팅 (Hoisting)</h3>
<p>   1) 호이스팅 : 자바스크립트에서 코드를 위에서 아래로 읽어가기전, 변수,함수, 클래스 등의 선언부를 먼저 읽어들이는 작업</p>
<p>   2) function은 function구문 전체가 먼저 읽어들여짐 =&gt; function은 함수 표현식으로 쓰되, 함수 선언식이 필요할 경우가 있기에 상황에 맞춰서 사용</p>
<p>   3) var을 사용하는것은 지양(같은 이름의 변수를 두번 선언 하는 것도 가능하며 전역 변수에 또 바로 등록해 선언하는 것도 가능), let과 const를 활용</p>
<p>   4) var와 let,const가 호이스팅 관련해서 다른 이유 :  호이스팅 과정에서 읽어들이는 부분에 차이가 있기 때문인데, 
                     - 변수 생성과정:  크게 1. 변수선언 2. 초기화(undefined) 3. 할당.  세 가지 과정 </br>
               - var는 호이스팅 과정에서 1.변수선언과 2.초기화까지 이루어짐 : 스코프의 유효범위 처음부터 변수가 선언된 위치 전까지</br>
                 var은 참조하여 초기화 값(undefined)를 끌어낼 수 있음</br>
               - let,const는 초기화가 안되어있는 상태라 var과 달리 reference erroe 발생. // 이러한 방시으로 참조할 수 없는 구간을 일시적 사각지대라 하여 TDZ라고 한다
</br></br></br></p>
<h3 id="2-tdz-temporal-dead-zone-">2. TDZ (temporal Dead Zone) :</h3>
<p>   1) TDZ은 let, const, class 구문의 유효성을 관리<br>   2) var, function, import 구문은 현재 scope에서 hoisting되기 때문에 TDZ의 영향을 받지 않는다.
   3) typeof 연산자는 변수가 현재 스코프 안에 선언되었는지 확인 시 유용. TDZ 안에서는 다르게 동작</p>
<pre><code class="language-javascript">      //TDZ는 선언문이 존재하는 scope 범위 안에서 변수에 영향을 줌.
      function doSomething(someVal) {
      // Function scope
      typeof variable; // =&gt; undefined
      if (someVal) {
          // Inner block scope
          typeof variable; // throws `ReferenceError`
          let variable;
        }
      }

      doSomething(true);
</code></pre>
]]></description>
        </item>
    </channel>
</rss>