JavaScript/알고리즘

프로그래머스 같은 숫자는 싫어 JS (for문 / 스택 이용하기)

hihiha2 2023. 11. 1. 00:18

🧷 링크 

문제 설명

배열 arr가 주어집니다. 배열 arr의 각 원소는 숫자 0부터 9까지로 이루어져 있습니다. 이때, 배열 arr에서 연속적으로 나타나는 숫자는 하나만 남기고 전부 제거하려고 합니다. 단, 제거된 후 남은 수들을 반환할 때는 배열 arr의 원소들의 순서를 유지해야 합니다. 예를 들면,

  • arr = [1, 1, 3, 3, 0, 1, 1] 이면 [1, 3, 0, 1] 을 return 합니다.
  • arr = [4, 4, 4, 3, 3] 이면 [4, 3] 을 return 합니다

배열 arr에서 연속적으로 나타나는 숫자는 제거하고 남은 수들을 return 하는 solution 함수를 완성해 주세요.

 

 

🙋‍♀️ 내 생각

스택 / 큐를 공부하면서, 실제 코드로도 연습하고 싶어서 풀어본 문제이다.

프로그래머스에서도 스택/ 큐 문제만 따로 모아두어서 찾아서 풀어보기도 쉽다.

 

🧷 프로그래머스 스택 / 큐 문제모음집

 

그중 첫번째 문제Level1으로 스택/큐 문제중에서는 난이도가 가장 낮은 문제였다.

 

연속적으로 같은 숫자가 있을 경우, 하나만 남기고 나머지는 제거한다.

 

여기에서 주의할 점중복을 제거하는 것이 아니라는 것이다.

처음에 문제를 읽고 중복제거만 하는건가? set()을 사용할까 했는데, 자세히 읽어보니 중복을 제거하는 문제가 아니라 동일 숫자가 반복된 경우 하나만 남기는 문제라는 것을 알게되었다.

 

예를 들면, 입출력 예1번과 같이 1이 중복되었지만 앞과 뒤의 1이 모두 남아야한다.

 

 

그래서 배열을 돌면서 각각 앞칸 뒤칸에 같은 값 같은지/ 다른지를 비교해야겠다고 생각했다.

(배열을 돌기 위해서는 for문을 사용했다.)

만약 같은 값이 있다면, 그중 하나만을 취한다.

이렇게 취한 값만을 넣어줄 배열을 만들어서 해당값들만으로 채워나간다.

 

 

 

 

✅ 내 코드

function solution(arr){
    const newArr = []
    
    for(i=0; i<arr.length; i++){
        if(arr[i]!==arr[i+1]){
            newArr.push(arr[i])
        }
    }
    return newArr
}

 

우선 해당되는 값들을 넣어줄 배열을 []로 빈배열로 만든다.

 

그러고 나서 for문을 통해서 반복문을 만든다.

반복문의 범위는 i=0부터 시작해서 arr.length보다 작을때까지 +1씩 더한다.

(이렇게해서 배열의 길이만큼 전부 검사한다.)

 

for문의 안에서는 if문을 통해서 붙어있는 두개의 값들이 다른지를 검사한다.

arr[i]!==arr[i+1]

 

같지 않은지를 검사하여, 두개의 값이 다를때만을 추출하는 방법이다.

(같은 값은 모두 추출할 필요가 없으므로, 값이 다를때만을 뽑아내는 것)

 

그래서 값이 다르면, 그 값을 맨처음에 빈배열로 만들어두었던 newArr에 push를 통해서 추가한다.

이렇게 하면 동일값들은 pass하고 값이 앞뒤의 값이 다를때만을 newArr에 저장할 수 있다.

 

일단 문제를 빨리 풀려고 생각나는 방식으로 풀었는데, 이것도 빈배열을 이용하고 push를 이용한다는 점에서 일종의 스택구조이지만,

수가 같은지 비교자체를 스택구조로 할 수도 있을 것 같아서 다른 스택을 이용한 방식으로도 코드를 바꿔보았다.

 

일단, 이러한 방식을 이해하기 위해서는 스택에 대한 개념이 필요하다.

스택나중에 들어간 것이 가장 먼저 나오는 후입선출의 형태의 데이터 저장 구조를 의미한다.

 

더 자세한 내용은 아래의 포스팅에 정리해두었다.

 

스택, 큐 / ADT, DS 자료구조 / JS의 스택과 큐

스택과 큐는 컴퓨터의 메모리, 자바스크립트의 런타임원리등 공부할 때 자주 등장한 개념이다. 어느정도 익숙한 개념이지만 정확하게 이해하기 위해서 공부해보았다. 스택과 큐는 자료구조를

hihiha2.tistory.com

 

 

 

 

✅ 스택을 이용한 코드

stack을 이용하면,

위에서 for문으로 앞뒤칸의 요소들을 비교한 뒤 배열에 담았던과는 달리, stack안에 들어있는 값현재의 값을 비교한다.

위의 코드 스택을 이용한 코드
arr[i]!==arr[i+1] stack[stack.length - 1] !== num
앞 !== 뒤 스택의 맨 위에 있는 요소 !== 현재 요소

스택의 맨 위에 있는 요소와 현재요소가 같지 않을때만 그 값을 스택에 담는다.

 

 

function solution(arr) {
    const stack = []; 
    
    for (const num of arr) {
        if (stack.length === 0 || stack[stack.length - 1] !== num) {
            stack.push(num);
        }
    }
    
    return stack;  
}

 

우선, stack이라는 이름으로 초기화한다.

 

그런 다음 for문을 만든다.

인덱스를 통한 값의 비교를 하지 않아도 되고, 전체요소를 한바퀴 돌아야하기때문에 for of문을 이용한다.

for (const element of array1) {
  수행할 코드
}

 

for of 문은 반복가능한 객체에서 각 개별 속성에 대해 코드를 실행할 수 있다.

arr의 모든 요소를 돌면서, 각 요소를 만나면 for문안에 있는 수행문을 수행한다.

이때 각각의 현재요소가 바로  num이다.

 

스택을 이용할 때 주의할 점은

초기에는 스택이 비어있기때문에  stack.length===0을 통해서 스택이 비워있을 때를 처리해야한다는 점이다.

스택이 비어있는 경우는 무조건 일단 담는다.

 

비어있지 않을 경우에는  stack[stack.length-1]!==num을 통해서 스택의 가장 위의 값과 현재요소를 비교한다.

두개의 값이 다를때만 스택에 담는다.

 

➡️ 두개의 조건중 하나만 만족하면 되므로, stack.length === 0 || stack[stack.length - 1] !== num  로 ||를 통해서 한줄로 만든다.

 

위의 조건을 만족하면 push를 통해서 해당 값(num)을 스택에 담는다.

 

push()는 배열의 가장 마지막에 추가된다는 특성을 지니고 있기때문에, 해당 값들이 스택안에 차례로 담기게된다.

 

 

예를 들어,

입출력 예1의 스택구조는 아래와 같다. (Last In First Out)

1
0
3
1

 

 

🙋‍♀️ 내 생각

for문만 이용해도 간단하게 풀수있는 문제이다. 그래도 스택의 구조를 더 잘 이해하고 싶어서 푼 문제이기때문에 스택을 한번더 이해하면서 풀면 좋을 것 같다.

 

스택은 가장 마지막에 들어간 값이 맨 위에 위치하고 있다.

또 그렇기때문에 데이터를 이용할때 push()pop()처럼 마지막에 추가하거나, 마지막값만을 삭제하는 메서드를 이용한다.

 

개념으로 공부하던 것을 이렇게 알고리즘을 통해서 그 구조를 이용해서 문제를 풀어보니 좋았다.

 

이 문제를 풀어봄으로서,

stack구조를 이용할때는 1. stack이 비어있을 경우 처리하기 2. stack의 비교는 가장마지막 값과! 가 핵심인것 같다고 생각했다.