Skip to content

[oh-chaeyeon] 25.01.09#21

Merged
JooKangsan merged 21 commits intomainfrom
ohchaeyeon
Jan 16, 2025
Merged

[oh-chaeyeon] 25.01.09#21
JooKangsan merged 21 commits intomainfrom
ohchaeyeon

Conversation

@oh-chaeyeon
Copy link
Collaborator

[배열]

스택의 기본 개념 이해하기!!!

  • 스택은 “후입선출(LIFO, Last In First Out)" 방식으로 동작함. → 가장 나중에 추가된 데이터가 가장 먼저 제거된다는 의미.

가장 많이 사용하는 메서드

  1. push() : 스택에 값을 추가
  2. pop() : 스택에서 값을 제거
  3. peek() : 스택의 최상단 값을 확인(배열의 마지막 요소 확인)
const stack = [];
stack.push(1); // [1]
stack.push(2); // [1, 2]
console.log(stack.pop()); // 2 (스택에서 제거됨)
console.log(stack); // [1]
console.log(stack[stack.length - 1]); // 1 (스택의 최상단 값 확인)

+그리고 챗gpt 이용해서 스택 관련된 문제들 풀어보면서 공부함.

📌 푼 문제


📝 간단한 풀이 과정

문자열 뒤집기

  • split('') 메서드로 문자열을 배열로 나누고, reverse() 메서드로 배열을 뒤집은 후, join('') 메서드로 다시 문자열로 합치는 방법으로 문자열 뒤집기!
function solution(my_string) {
  return my_string.split("").reverse().join("");
}

컨트롤 제트

  • 문제설명 : Z를 만나면, 전에 바로 더한 갑을 빼는 걸 반복하면서 결과값을 반환하기
  • Z 만나면 바로 이전 숫자를 total에서 빼주고, 숫자면 계속 더하면서 최종값 구하기.
function solution(s) {
  const elements = s.split(" "); // 문자열을 공백으로 나누어 배열로 변환
  let total = 0;

  for (let i = 0; i < elements.length; i++) {
    if (elements[i] === "Z") { // Z를 만나면, 마지막 숫자를 빼기
      total -= parseInt(elements[i - 1]);
    } else {
      total += parseInt(elements[i]); //꼐속해서 숫자 더해주기
    }
  }

  return total;
}

영어가 싫어요

  • 정규 표현식이란? 특정한 규칙을 가진 문자열을 찾거나 대체할 때 사용하는 패턴
  • 정규 표현식의 기본구조
const regex = /패턴/옵션;
  • /패턴/ : 찾고자 하는 문자열의 규칙(패턴)을 정의.
  • 옵션 : 정규 표현식의 동작 방식을 제어.
    → g : 전체 검색 (global match) → 일치하는 모든 항목을 찾음
    → i : 대소문자 구분 없음 (case-insensitive match)

문자열에서 단어 치환하기

const text = "onetwothree";
const regex = /one|two|three/g;

const result = text.replace(regex, match => {
    if (match === "one") return "1";
    if (match === "two") return "2";
    if (match === "three") return "3";
});
console.log(result); // "123"
  • 문제해결방법 : 정규표현식으로 문자열에서 숫자 단어를 찾아내고, 매핑 객체를 사용하여 단어를 숫자로 변환하는 방식으로 문제를 해결함.
  • 매핑이란? 특정 값(키)에 대해 다른 값을 대응시키는 방식
function solution(numbers) {

  // 정규표현식으로 문자열에서 "zero"부터 "nine"까지의 단어를 찾아 매칭된 단어를 숫자로 변환
  return parseInt(
    numbers.replace(
      /zero|one|two|three|four|five|six|seven|eight|nine/g, 
      (match) => {

       // 매칭된 단어를 숫자로 매핑
        const numWords = {
          zero: "0",
          one: "1",
          two: "2",
          three: "3",
          four: "4",
          five: "5",
          six: "6",
          seven: "7",
          eight: "8",
          nine: "9",
        };
        return numWords[match]; // 매칭된 단어를 numWords에서 대응되는 숫자로 변환
      }
    )
  );
}

문자열 계산하기

  • 문자열 수식을 직접 계산해주는 JavaScript 내장 함수인, eval 함수를 사용함.
  • eval 함수를 사용하면 간단하게 문제를 해결할수 있지만, 보안상의 위험이 있다고 함.
function solution(my_string) {
  return eval(my_string);
}

크레인 인형뽑기 게임

  • 이런 문제는 왜 이렇게 문제를 이해하기 힘든건지,,,,,,,,
function solution(board, moves) {
  const basket = []; //바구니 역할
  let count = 0; // 터진 인형을 카운트하는 변수

  for (let move of moves) {
    const column = move - 1; // 크레인이 선택한 열 (0부터 시작하므로 -1)

     // 해당 열에서 가장 위에 있는 인형 찾기
    for (let i = 0; i < board.length; i++) {
      if (board[i][column] !== 0) { // 인형이 있다면 인형을 집어올리고, 집은 자리는 0으로 채우기
        const doll = board[i][column];
        board[i][column] = 0;

         //인형 집어서 바구니에 넣기
        if (basket[basket.length - 1] === doll) { // 바구니 맨 위와 동일한 인형이면 터뜨림
          basket.pop();
          count += 2; // 두 개 터졌으므로 카운트변수에 +2
        } else {
          // 아니면 바구니에 추가
          basket.push(doll);
        }
        break;
      }
    }
  }

  return count;
}

올바른 괄호

  • '(' 또는 ')' 로만 이루어진 문자열이 주어지기 때문에, 별도의 객체를 두지 않음.
  • 열리는 괄호 '('는 무조건 stack에 추가하고, 닫히는 괄호 ')'는 stack이 비어있지 않은 경우에만 pop.
  • 문자열을 순회할 때, 닫히는 괄호가 나왔을 때 stack이 비어 있으면 잘못된 괄호이므로 false 반환.
  • 순회를 끝낸후, 스택이 비어있으면 모두 짝지어져 있으므로 true, 값이 남아있으면 짝지어지지 않은 괄호가 존재함으로 false를 반환.
function solution(s) {
  const stack = [];

  for (let char of s) {
    if (char === "(") {
      stack.push(char);
    } else if (stack.length > 0) {
      stack.pop();
    } else {
      return false;
    }
  }

  return stack.length === 0;
}

다트 게임

  • 총 3번의 기회 (각 기회마다 얻을수 있는 점수는 0~10점)
  • S → 점수, D → 점수점수, T → 점수점수*점수 (보너스는 S, D, T 중 하나)
  • * → 2배, # → 현재 점수를 음수로 만듦. (옵션은 둘 중 하나만 존재하거나 둘 다 없을수 있음)

1S2D3T → 37 풀이: 1 * 2 + 22 * 2 + 333
1D2S0T → 3 풀이: 1 + 2 + 000
1S2T3S → 23 풀이: 1* 2 * 2 + 222 * 2 + 3
1D#2S*3S → 5 풀이: 1 * (-1) * 2 + 2 * 2 + 3

function solution(dartResult) {
  const stack = []; //점수를 저장하는 배열
  let i = 0;

 // 처음부터 끝까지 순회하면서 처리
  while (i < dartResult.length) {
    
    // 숫자 추출
    const isTen = dartResult[i] === "1" && dartResult[i + 1] === "0";
    let score = isTen ? 10 : parseInt(dartResult[i]); // 10점은 두 자리 숫자이므로 isTen 조건을 추가해 처리
    i += isTen ? 2 : 1;

    // 보너스 처리
    const bonus = dartResult[i++];
    score **= bonus === "S" ? 1 : bonus === "D" ? 2 : 3;

    // 옵션 처리
    if (dartResult[i] === "*" || dartResult[i] === "#") {
      score *= dartResult[i] === "*" ? 2 : -1;
      if (dartResult[i++] === "*" && stack.length) {
        stack[stack.length - 1] *= 2;
      }
    }

    stack.push(score);
  }

  return stack.reduce((sum, cur) => sum + cur, 0);
}

괄호 회전하기

  • 문제 설명 : 문자열 s를 회전시켜가며, 각 회전된 문자열이 올바른 괄호 문자열인지를 확인하는 문제
  • 함수를 만들어서 처리
  1. solution 함수의 역할 : 입력받은 문자열 s를 한 칸씩 회전시켜 모든 경우를 확인
  2. isValid 함수의 역할 : 입력받은 문자열이 "올바른 괄호 문자열"인지 확인 = 괄호의 짝이 맞고, 모든 괄호가 닫혔는지 검증
  3. isPair 함수의 역할 : 여는 괄호와 닫는 괄호가 짝이 맞는지 확인하는 함수
function solution(s) {
  let answer = 0; // 올바른 괄호 문자열의 개수를 저장
  for (let i = 0; i < s.length; i++) { 
    const rotated = s.slice(i) + s.slice(0, i);
    if (isValid(rotated)) answer++; // 회전된 문자열이 올바른 괄호 문자열인지 확인하고 맞다면 answer증가시킴
  }
  return answer;
}

function isValid(str) {
  const stack = []; 
  for (let c of str) {  // 문자열의 각 문자를 순회
    if ("([{".includes(c)) stack.push(c); // 열린 괄호라면 스택에 추가
    else if (!stack.length || !isPair(stack.pop(), c)) return false; // 닫힌 괄호인데 스택이 비어있거나 짝이 맞지 않으면 false 반환
  }
  return stack.length === 0;
}

function isPair(open, close) { // 맞는 쌍이면 true, 그렇지 않으면 false를 반환하도록 함.
  return (
    (open === "(" && close === ")") ||
    (open === "[" && close === "]") ||
    (open === "{" && close === "}")
  );
}

주식가격

  • 이 문제도 처음에 "떨어지지 않다"라는 의미가 이해가 안되어서 힘들었다는...
  • 떨어지지 않다의 의미 = 현재 시점의 가격이 이후 시점의 가격보다 작지 않거나 같음.
  • 따라서, 떨어지는 경우는 이후 시점의 가격이 현재 가격보다 작아지는 순간을 말함.
function solution(prices) {
  const answer = Array(prices.length).fill(0); // 각 주식 가격이 떨어지지 않은 시간을 저장할 배열
  const stack = []; // 스택을 사용해 가격이 떨어지지 않은 주식의 인덱스를 저장

  prices.forEach((price, i) => { // forEach를 사용해서 i와 price를 한번에 가져와서 처리
    //  현재 가격이 이전 가격보다 낮으면, 스택에서 인덱스를 꺼내서 떨어지기까지의 시간을 계산.
    while (stack.length && prices[stack[stack.length - 1]] > price) {
      const idx = stack.pop();
      answer[idx] = i - idx;
    }
    stack.push(i);
  });

   // 스택에 남은 인덱스는 끝까지 가격이 떨어지지 않은 경우
  stack.forEach((idx) => { 
    answer[idx] = prices.length - 1 - idx; // 끝까지 유지된 시간을 저장
  });

  return answer;
}

택배상자

  • 문제 : order : [ 4, 3, 1, 2, 5 ]일때, 4번 상자를 꺼내기 위해 보조 컨테이너 벨트에 1,2,3 순서대로 저장후 4번 상자를 트럭에 실음.다음, 보조 컨테이너 벨트에서 3번 상자를 꺼내서 트럭에 실음. 다음 보조 컨테이너 벨트에서 1번 박스를 꺼내기에는 2번 박스가 막고 있음으로 1의 상자는 트럭에 실을 수 없음. 따라서 트럭에 실을 수 있는 상자는 4번, 3번 상자이므로, 결과값은 2이다.
  • 스택을 사용해 보조 컨테이너 벨트를 구현하고, while 루프를 통해 상자를 꺼내면서 원하는 순서에 맞춰 트럭에 실릴 수 있는 최대 개수를 계산하도록 함.
function solution(order) {
  let stack = []; // 보조 컨테이너 벨트로, 상자를 임시로 보관가능.
  let current = 1; // 현재 꺼내야 할 상자의 번호, 1부터 시작
  let count = 0; // 트럭에 실은 상자의 개수

  for (let box of order) {

    // 현재 상자 번호(current)가 처리해야 할 상자(box)보다 작거나 같을 때까지 상자를 스택에 추가
    while (current <= box) {
      stack.push(current++);
    }

    // 스택에서 가장 위의 상자를 꺼내어 현재 처리해야 할 상자(box)와 비교
    if (stack.pop() === box) { //꺼낸 상자가 현재 상자와 같으면 count증가, 다르면 루프 종료
      count++;
    } else { 
      break; 
    }
  }

  return count;
}

@oh-chaeyeon oh-chaeyeon self-assigned this Jan 12, 2025
Copy link
Collaborator

@Moonjonghoo Moonjonghoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전체적으로 간결하게 코드를 짜주셔서 보기편했습니다.
한주 고생하셨습니다.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

정규식을활용하여 코드가 직관적이라 좋았습니다!

Copy link
Collaborator

@JustDevRae JustDevRae left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고 많으셨습니다! 자세한 설명 덕분에 이전에 풀지 못했던 문제들도 이해하면서 리뷰할 수 있었습니다!

@JooKangsan JooKangsan merged commit 5e01451 into main Jan 16, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants