본문 바로가기

알고리즘

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

1. 문제 정보

2. 손코딩

3. 코드
4. 어려웠던 부분 || 배운 것

5. 다른 사람의 풀이

 

1. 문제 정보

1) 출처: https://school.programmers.co.kr/learn/courses/30/lessons/87390

2. 손코딩 (아래와 같은 로직으로 풀었지만 효율성 테스트를 통과하지 못함)

1) 처음부터 right 인덱스까지 순회하면서 숫자들을 채워 놓는 식으로 처음에 구현

2) 배열의 길이를 n 으로 나눴을 때 나머지가 0 인지 아닌지를 먼저 기준으로 잡음
2-1-1) 배열의 길이를 n 으로 나눴을 때 나머지가 0 이면 ( row를 +1, column = 1, answer 에 넣을 숫자를 다시 세팅해줘야 한다 )
2-1-2) num를 다시 세팅하기 위해 현재 row의 첫번째 숫자를 prevNum 에 세팅
2-1-3) num = prevNum + 1;

2-2-1) 배열의 길이를 n 으로 나눴을 때 나머지가 0 이 아니면 (  answer 에 넣을 숫자만 잘 세팅해주면 된다 )
2-2-2) 현재의 숫자와 prevNum이 같으면 prevNum 만큼 num을 answer 에 추가
2-2-3) 현재의 숫자와 prevNum이 다르면 num을 answer 에 추가

3) num = num + 1

4) 처음부터 right 까지 answer 에 숫자들이 들어갔으니 left 인덱스부터 rigth 까지 잘라서 반환

3. 코드 (통과 못 함, 첫 번째 코드는 테스트코드 12~ 런타임 에러, 두 번째 코드는 테스트 코드 모두 실패)

function solution(n, left, right) {
    var answer = [];
    let num = 1;
    let prevNum = 1;
    let index = 0;
    
    while (answer.length < right + 1) {
        if (answer.length > 0 && (answer.length + 1) % n === 0) {
            answer.push(num); // [1, 2, 3]; // num = 3
            num = prevNum + 1; // num = 2;
            prevNum = prevNum + 1; // prevNum = 2;
        } else { // n의 배수가 아닐 때 
            if (num === prevNum) {
                for (let i = 0; i < prevNum; i++) {
                    answer.push(num); // [1]
                }
            } else {
                answer.push(num);
            }    
            
            num = num + 1;
        }
        
    }
    
    return answer.slice(left, right + 1);
}

console.log(solution(3, 1, 1));

 

function solution(n, left, right) {
    var answer = [];
  
    let answerLength = right - left + 1; // 4
    let restLength = (n * n) - answerLength; // 5
    let rightLength = restLength - left; // 3
    let leftLength = restLength - rightLength; // 2
    let startRowNum = parseInt(left / n) + 1; // 1
    let startColumNum = (left % n) + 1; // 3
  
    let startNum = 1;
    let prevNum = 1;
  
    if (startRowNum < startColumNum) { // 1 < 3
      startNum = startColumNum;
    } else if (startRowNum > startColumNum ) {
      startNum = startRowNum;
    } else {
      startNum = startRowNum;
    }
  
    while (answer.length !== answerLength) {
        debugger;
        if (startColumNum % n === 0) {
            answer.push(startNum); 
          
            startNum = prevNum + 1;
            prevNum = prevNum + 1; 
            startColumNum = 1;
        } else { 
            if (startNum === prevNum) {
                for (let i = 0; i < prevNum; i++) {
                    answer.push(startNum);
                }
            } else {
                answer.push(startNum);
                startColumNum++;
            }    
            
            startNum = startNum + 1;
        }
        
    }
  
    console.log(answer);
    
    return answer;
}

4. 어려웠던 부분 || 배운 것

1) 패턴을 보면 answer에 들어가는 값들은 현재 row, 현재 column 중에 큰 값 + 1이 value로 들어간다.

1 (0, 0) 2 (0, 1) 3 (0, 2)
2 (1, 0) 2 (1, 1) 3 (1, 2)
3 (2, 0) 3 (2, 1) 3 (2, 2)

2) row 값은 Math.floor(left / n) 으로 구할 수 있다. x 좌표에 해당함


3) column 값은 left % n 으로 구할 수 있으나 while 구문을 계속 돌기 위해서 left++ % n을 해주면 된다. 그러면 column, y축에 대한 정보를 얻을 수 있다.

4) Math.max 메서드를 이용해서 x, y좌표 중 더 큰 값을 max 로 잡고 + 1 을 해주면 해당 좌표에 해당하는 값을 구할 수 있다.

 

5. 다른 사람의 풀이 👍👍

function solution(n, left, right) {
    const answer = [];
    
    while (left <= right) {
        answer.push(Math.max(Math.floor(left / n), left++ % n) + 1)
    }
    
    return answer;
}