티스토리 뷰

처음에 문제를 예시까지 싹 읽고 든 생각은

먼 개소리야?(넝담ㅎ)

 

힌트를 보고서야 무슨 말인지 이해할 수 있었다.

1234567...n 까지의 오름차순의 수들을 스택에 push하는 것까지는 변하지 않는 고정된 상황.

여기서 pop하는 숫자들을 순차적으로기록해서 주어진 수열을 만족할 수 있냐는 소리였다.

 

43687521의 경우, 1234 push(++++) 4 pop(-) 3 pop(-) 56 push(++) 6 pop(-) 78 push(++) 87521 pop(-----) 이므로 조건을 만족한다.

12534의 경우 1 push(+) 1 pop(-) 2 push(+) 2 pop(-) 345 push(+++) 5 pop(-) 이후 무조건 4 pop만 가능하기에 조건을 만족하지 못한다.

 

12345...n까지의 값을 stack에 push한다고 하면, stack의 특성 상 n까지 push한 뒤로는 pop만 가능하다.

여기서 파악한 규칙성은

1. Max 이후의 값 :
      내림차순이다.
2. Max 이전의 값 :
      이전값보다 작은 수의 경우, 해당 값이 되기 전에 사이에 있는 값들이 이전에 pop되었다.
or   없다. (ex. 87654321)

이었다.

 

이를 통해, 먼저 해당 수열이 push pop 연산으로 만들어질 수 있는가를 선판단 한 후,

아니라면 NO 출력 후 end

맞다면 연산을 하면 된다.

 

그렇다면 push pop을 빠르게 계산하기 위한 규칙성은 없을까?

max값 이전의 값들은 규칙성을 확인할 수 있었는데,

 

43687521의 예시를 다시 끌어와보겠다.

여기서 max값을 포함한 앞의 값은 4368이다.

1부터 순차적으로 push하는 것을 고려하면, 4는 최소 push 4번을 강제한다.

+ + + + -

이후 값은 감소한다면, pop 한번.

-

이후 값이 증가한다면, 이전값(3)에서 해당값까지 push... 뭐 이런식으로 값 비교후, 차잇값만큼 +를 써주고 - 써주고...


문제 파악은 끝난 것 같아 코드를 작성해보았다.

function solution(inputArray){
  let count = +inputArray[0]; //count===max
  let resultlog = [];
  inputArray.splice(0, 1);

  var maxIndex = inputArray.indexOf(count);

  for(let i = 0, previousMax = 0; i < count; i++) {
    if(i === 0) { //  *** i 처음일 때 ***
      for(let j = 0; j < inputArray[i]; j++) {
        resultlog.push('+');
      }
      previousMax = inputArray[i];
      resultlog.push('-');
      continue;
    } else if(i <= maxIndex) { //  *** max 이전 값일 때 ***
      if(inputArray[i] < inputArray[i-1]) { // ** 값이 감소했을 때 **
        for(let j = inputArray[i]+1; j < inputArray[i-1]; j++) {
          if(inputArray.indexOf(j) < i) { //  * 사잇값들이 이전에 pop되었다 : O

          }else { //  * 사잇값 중 이전에 pop되지 않은 것이 있다 : X
            resultlog.push('NO');
            break;  //for문을 한 번 더 break해야 함.
          }
        }

        if(resultlog[resultlog.length-1] === 'NO') {
          break;
        } else {
          resultlog.push('-');
        }
      }else { //  ** 값이 증가했을 때 **
        for(let j = previousMax; j < inputArray[i]; j++) {
          resultlog.push('+');
        }
        resultlog.push('-');
      }
    } else if(i > maxIndex) { //  *** max 이후 값일 때 ***
      if(inputArray[i-1] < inputArray[i]) { //  **  값이 증가했을 때 : X **
        resultlog.push('NO');
        break;
      } else {  //  **  값이 감소했을 때 : O **
        resultlog.push('-');
      }
    }
    if(previousMax < inputArray[i]) {
      previousMax = inputArray[i];
    }
  }
  if(resultlog[resultlog.length-1] === 'NO') {
    console.log('NO');
  } else {
    console.log(resultlog.join('\n'));
  }
}

그냥 조건 검색도 하면서, 로그 수정도 하도록 했다.

그치만..

어카지..

검색해보니까 나처럼 문제를 접근한 사람은 거의 없는 것 같았다...

대부분이 직접 스택에 넣고 거기서 오류가 나면 NO를 반환하는 코드를 짠 것 같았음...

나도 그렇게 짜야하나 고민했는데, 짜놓은 거 아깝기도 해서 일단 시간을 잡아먹는 요소를 찾아 해결해보려고 했다.

 

        for(let j = inputArray[i]+1; j < inputArray[i-1]; j++) {
          if(inputArray.indexOf(j) < i) { //  * 사잇값들이 이전에 pop되었다 : O

나는 여기서 indexOf가 시간을 오지게 잡아먹으리라 생각했다.

왜냐면 저 함수 자체로도 아마 수열 전체를 순회하며 돌테고,

사실상 내가 검사해야 하는 부분은 맨 앞부터 i 이전까지만임에도 불구하고 다 검사를 하고있을테니까

 

아쉽게도 정해진 index까지만 검사하는 방법은 없었지만, 반대로 정해진 index부터 검사를 시작할 수는 있었다.

그리고 뒤부터 검사하는 lastIndexOf 라는 함수를 발견했다. 역시 정해진 인덱스부터 역순으로 검사가 가능하다.

그러면 lastIndexOf에 i-1 index를 넣어주면 내가 원하는 범위만 검사를 하지 않겠는가?

        for(let j = inputArray[i]+1; j < inputArray[i-1]; j++) {
          let index = inputArray.lastIndexOf(j, i-1);
          if(index < i && index > -1) { //  * 사잇값들이 이전에 pop되었다 : O

          }else { //  * 사잇값 중 이전에 pop되지 않은 것이 있다 : X
            resultlog.push('NO');
            break;  //for문을 한 번 더 break해야 함.
          }
        }

lastIndexOf로 바꿔서 다시 코드를 돌렸다.

(저 if else 문이 흉측하고 비효율적이긴 한데... 일단 수정은 안했다... 당시엔 코드 돌아가는게 더 중요했고 변수를 만들고 싶지 않았음. if문의 조건을 뒤집고 else문 내부 코드를 if문으로 옮겨주고 else를 지우면 되겠쬬...?)

바로 해결됨... wow.....

 

그치만 다른 Nodejs 이용자 채점 현황을 보니 시간이 200-300ms에서 끝나는 코드들이 절반가량 되었다.

아마 앞서 언급한 방식으로 구현하면 시간이 많이 단축되는 게 아닐까...?

시간 될 때, 저 스택 직접 구현 방식으로 구현해봐야겠다. 

'■ 알고리즘 > ◻ 백준' 카테고리의 다른 글

[Nodejs]10845번: 큐  (0) 2022.08.02
[Nodejs]1406번: 에디터  (0) 2022.08.02
[Nodejs]9012번: 괄호  (0) 2022.07.22
[Nodejs]9093번: 단어 뒤집기  (0) 2022.07.20
[Nodejs]10828번: 스택  (0) 2022.07.20
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/11   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
글 보관함