개발조각

[프로그래머스] n^2 배열 자르기 본문

알고리즘🅰/프로그래머스

[프로그래머스] n^2 배열 자르기

개발조각 2022. 3. 13. 18:30
728x90
반응형

드디어 프로그래머스 Level 2로 넘어갔습니다.😆

야심 차게 레벨 2로 넘어갔지만 확실히 문제가 길고 그 문제를 이해하는 시간도 오래 걸리고 문제는 푸는데 정확성 테스트에서 통과 못하는;;;😭

그런 상황이 와서 최대한 완료 숫자가 많은 문제부터 풀기로 했습니다.

 

 

위에 설명을 쉽게 설명한다면

테스트 1 (n=3; left=2; right=5)

1 2 3
2 2 3
3 3 3

1,2,3 2,2,3 3,3,3

 

여기서 index순서로 0부터

left = 2 -> 3, right = 5 ->3

1,2,3 2,2,3 3,3,3

result = [3,2,2,3]

 

테스트 2 (n=4; left=7; right=14)

1 2 3 4
2 2 3 4
3 3 3 4
4 4 4 4

1,2,3,4 2,23,4 3,3,3,4, 4,4,4,4

 

여기서 index순서로 0부터

left = 7 -> 4, right = 14 ->4

1,2,3,4 2,23,4 3,3,3,4, 4,4,4,4

result = [4,3,3,3,4,4,4,4]


해결방안

function solution(n, left, right) {
    var answer = [];
    
    for(let i=left; i<right+1; i++){
        let a = Math.floor(i/n);
        let b = i%n
        b<a ? answer.push(a+1) : answer.push(b+1);
    }
    return answer
}

 

해결방안 보시면 이렇게 쉬운데? 이러실 수 있습니다.

그렇지만 이 답을 알기 위한 과정이 험난했습니다...

프로그래머스는 정확성 테스트에서 테스트 몇 번이 틀렸는지 만 알려주지 왜 틀렸는지에 대해서는 안 알려 주거든요😓

풀 때 최대한 효율성(어떻게 하면 코드가 더 짧게 실행하고 끝낼 수 있을까?)을 생각하시고 푸시면 좋을 것 같습니다.

 

 

1. i를 left부터 right까지만 돌리기 -> for(let i=left; i<right+1; i++)

이 문제에서 가장 중요한 포인트라고 생각합니다.

제가 처음에는 n이 무엇이냐에 따라 배열을 다 만들고 그 뒤에 left부터 right까지 잘랐는데요.

이렇게 하시면 절대로 정확성 테스트에서 통과를 못합니다.

 

왜냐하면 효율성을 생각했을 때

n에 대한 배열을 다 만들고 left부터 right까지 자르면 시간이 너무 걸리거든요.

그래서 애초부터 "for문에서 left부터 right까지 값 구하고 return 해주면 for문을 적게 돌리고 바로 끝내고 효율성 있게 구할 수 있겠다"라고 생각했습니다.

 

2. n^2 배열의 각 자리에 무슨 숫자인지 구하기

let a = Math.floor(i/n);
let b = i%n
b<a ? answer.push(a+1) : answer.push(b+1);

사실 풀다가 얻어걸린 거긴 한데요. 그래도 제가 푼 거니까 설명해보도록 하겠습니다.

여기서 중요한 포인트는 i에 n을 나누었을 때 값과  i 나누기 n의 나머지 값이 중요합니다.

(코드에서는 a, b 변수겠죠?)

 

이 두 가지 값에 따라 i번째의 수가 무슨 수인지를 구할 수 있습니다.

단순 무식하게 n^2에 때라 i번부터 n*n-1까지의 값과 a, b의 값을 쭉 써보았습니다.

let a = Math.floor(i/n); -> Math.floor 정수 빼고 나머지(소수) 버림
let b = i%n

테스트 2 (n=4; left=7; right=14)
[1,2,3,4,2,2,3,4,3,3,3,4,4,4,4,4]

i=0
a = 0/4 = 0
b = 0%4 = 0
-> a === b -> a+1 =1, b+1 = 1

i=1
a = 1/4 = 0
b = 1%4 = 1
-> a < b-> b+1 = 2

i=2
a = 2/4 = 0
b = 2%4 = 2
-> a < b -> b+1 = 3

i=3
a = 3/4 = 0
b = 3%4 = 3
-> a < b -> b+1 = 4
------------------------------
i=4
a = 4/4 = 1
b = 4%4 = 0
-> a > b -> a+1 = 2

i=5
a = 5/4 = 1
b = 5%4 = 1
-> a === b -> a+1 =2, b+1 = 2

i=6
a = 6/4 = 1
b = 6%4 = 2
-> a < b -> b+1 = 3

i=7
a = 7/4 = 1
b = 7%4 = 3
-> a < b -> b+1 = 4
------------------------------
i=8
a = 8/4 = 2
b = 8%4 = 0
-> a > b -> a+1 = 3

i=9
a = 9/4 = 2
b = 9%4 = 1
-> a > b -> a+1 = 3

i=10
a = 10/4 = 2
b = 10%4 = 2
-> a === b -> a+1 =3, b+1 = 3

i=11
a = 11/4 = 2
b = 11%4 = 3
-> a < b -> b+1 = 4
------------------------------
i=12
a = 12/4 = 3
b = 12%4 = 0
-> a > b -> a+1 = 4

i=13
a = 13/4 = 3
b = 13%4 = 1
-> a > b -> a+1 = 4

i=14
a = 14/4 = 3
b = 14%4 = 2
-> a > b -> a+1 = 4

i=15
a = 15/4 = 3
b = 15%4 = 3
-> a === b -> a+1 =3, b+1 = 3

이걸 보시면 규칙이 보이지 않나요?

저도 아이패드에 이걸 쭉 써보고 아!! 했어요ㅎㅎ

 

a와 b의 비교에 따라 i번째의 값을 구할 수 있습니다.

  • a> b : a+1만 가능
  • a===b : a+1, b+1 둘 다 가능
  • a <b : b+1만 가능

 

이걸 코드로 쓰면 

let a = Math.floor(i/n);
let b = i%n
b<a ? answer.push(a+1) : answer.push(b+1);

이렇게 되고 i번째의 숫자가 무엇인지 알게 되었으니

for문안 left부터 right까지의 숫자만 배열에 담아주면 됩니다.

 

참고로 a를 구할 때 소수점 자리는 필요가 없어서 i/n을 하고 소수점 자리는 버림을 해주었습니다.

MDN Web Docs
Math.floor() 함수는 주어진 숫자와 같거나 작은 정수 중에서 가장 큰 수를 반환합니다.

구문 : Math.floor(x);

  • x : 숫자.
// Math.floor()함수 예제
Math.floor( 45.95); //  45
Math.floor( 45.05); //  45
Math.floor(  4   ); //   4
Math.floor(-45.05); // -46
Math.floor(-45.95); // -46

여기까지 프로그래머스 n^2 배열 자르기 해결방안에 대해 설명해보았습니다.

 

728x90
반응형
Comments