본문 바로가기
내일배움캠프 TIL

2023-10-30 본 캠프 18일차 / 37일차 TIL

by KMS_99 2023. 10. 30.

2023-10-30 본 캠프 18일차 / 37일차 TIL

 

주요진행사항

- 유데미 강의 시청 (리액트)

- 알고리즘 문제풀이


유데미 강의 시청 (리액트)

학습 진도

섹션1 ~ 섹션 3 / 42강

 


학습내용

리액트란?

자바스크립트 라이브러리로 사용자 인터페이스를 만들기 위해 사용된다.

JavaScript와 Html 나아가 CSS 까지 하나로 묶어 사용자 인터페이스를 만든다.

 

리액트는 특히 싱글페이지 어플리케이션을 만들 때 사용하며, 하나의 페이지로 여러개의 페이지 처럼 구현할 수 있는 특징이 있다.

 

리액트는 컴포넌트 단위로 이루어져있다.

여기서 컴포넌트란 여러개의 프로그램 함수들을 모아 하나의 특정한 기능을 수행하도록 구성한 작은 단위이다. 컴포넌트 단위로 개발을 하면, 첫째로 기능단위 개발이 가능하며, 둘째로 코드 재사용성이 높아진다.

리액트와 컴포넌트는 땔 수 없는 관계로 리액트 === 컴포넌트 라고 생각해도 무방하다.

 

마지막으로 JSX에 대한 내용이다.

JSX는 JavaScript XML의 줄임말으로, 자바스크립트 내부의 XML 코드를 뜻한다.

리액트의 JS 파일 내부에는 JSX 가 포함되어있다. 여기서 XML은 우리가 계속 사용해왔던 HTML 코드를 뜻한다. 우리가 계속 배워왔던 자바스크립트는 HTML과 JS 파일이 분리되어있지만, 리액트는 그렇지 않다.

물론 자바스크립트 엔진 내부에서 이 파일이 그대로 읽히는 것이 아니라 코드를 변환해서 해석한다.

 

JSX를 사용하게 되면 JS와 HTML 코드를 연계하여 코드를 작성할 수 있다는 장점이 있다.

 

느낀점

이전에 리액트를 배워본 적이 있다.

그때는 프로젝트를 무작정 만들어 보았다면, 이제는 개념부터 차근차근 공부해보려고 한다.

내일부터 내일배움캠프에서 제공해주는 강의를 듣겠지만 오늘 수강한 유데미 강의도 참고해서 리액트 개념을 공부하겠다.

주특기 공부를 시작하니 설레는 마음이다.

 


알고리즘 문제풀이

뒤에 있는 큰수 찾기

문제 URL : https://school.programmers.co.kr/learn/courses/30/lessons/154539

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제 정보

  • 문제 설명
    정수로 이루어진 배열 numbers가 있습니다. 배열 의 각 원소들에 대해 자신보다 뒤에 있는 숫자 중에서 자신보다 크면서 가장 가까이 있는 수를 뒷 큰수라고 합니다. 정수 배열 numbers가 매개변수로 주어질 때, 모든 원소에 대한 뒷 큰수들을 차례로 담은 배열을 return 하도록 solution 함수를 완성해주세요. 단, 뒷 큰수가 존재하지 않는 원소는 -1을 담습니다.
  • 제한 사항
    4 <= numbers.length <= 1,000,000
    1 <= numbers[i] <= 1,000,000
  • 입출력 예
    numbersresult
    [2, 3, 3, 5] [3, 5, 5, -1]
    [9, 1, 5, 3, 6, 2] [-1, 5, 6, 6, -1, -1]

작성 코드

function solution(numbers) {
  let answer = new Array(numbers.length).fill(-1);
  let stack = [];

  for (let i = numbers.length - 1; i >= 0; i--) {
    while (stack.length !== 0 && stack.at(-1) <= numbers[i]) stack.pop();
    if (stack.length !== 0) answer[i] = stack.at(-1);
    stack.push(numbers[i]);
  }
  return answer;
}

코드 풀이

시간 복잡도를 효율적으로 구성하기 위해 stack 자료구조를 사용한다.

특정 인덱스 뒤에 해당 인덱스의 수보다 큰 수가 있을 때를 제외한다면 -1로 초기화가 되어있어야하기에 최초에 모든 인덱스의 수를 -1로 초기화한다.

let answer = new Array(numbers.length).fill(-1);

다음으로 stack 자료구조를 표현하기 위한 빈 배열 하나를 초기화 해준다.

let stack = [];

각 원소의 뒷쪽에 있는 수를 비교해야하기 때문에 마지막 인덱스 부터 반복문을 돌린다.

 

1. 내부 while 문

while (stack.length !== 0 && stack.at(-1) <= numbers[i]) stack.pop();

내부 while문에서는 stack의 마지막 인덱스와 현재 값을 비교한다. stack 내부에는 현재 인덱스의 값보다 큰값이 들어있어야 하기 때문에 만약 작은 값이 있다면 pop으로 마지막 인덱스의 값을 삭제한다. while문은 stack의 마지막 인덱스의 값이 현재 인덱스보다 큰값이 있거나 stack이 빈 배열이 될 때까지 반복한다.

 

2. 내부 if 문

if (stack.length !== 0) answer[i] = stack.at(-1);

내부 코드블럭의 첫줄에서 while문을 통해 stack을 필터링하였다. 만약 stack이 빈배열이 되었다면, 현재 인덱스의 값보다 큰값이 없다는 의미로 if문의 조건에 만족하지않아 실행되지 않는다. 빈배열이 아니라면, 현재 인덱스의 값보다 큰값이 있다는 것이고 가장 가까운 큰 값은 stack의 마지막 인덱스에 저장되어있을 것이다. 따라서 기본에 -1로 모두 초기화했던 answer 배열의 해당 인덱스의 값을 stack.at(-1), 즉 stack의 마지막 인덱스로 재할당한다.

 

3. stack에 현재 인덱스의 값 추가

stack.push(numbers[i]);

for문을 통해 마지막 인덱스부터 첫 인덱스까지 비교가 이루어지기 때문에 현재 인덱스의 값을 stack에 push 하면서 비교할 값을 stack에 할당한다.


시도한 코드

function solution(numbers) {
  let answer = new Array(numbers.length).fill(-1);

  for (let i = 0; i < numbers.length; i++) {
    const num = numbers[i];
    const delNumArray = numbers.slice(i + 1, numbers.length);
    const result = delNumArray.find((item) => num < item);
    if (result) {
      answer[i] = result;
    }
  }

  return answer;
}

해당 코드는 결과는 나오지만 시간복잡도 부분에서 문제가 있는 코드이다.
for문 안에 find을 사용한다면 중첩 반복문이 되어 시간 복잡도에서 효율이 떨어지는 문제가 있다.