작성일 : 2021년 12월 31일

문제 : https://programmers.co.kr/skill_checks/335618?challenge_id=9645

해설 : https://velog.io/@front/프로그래머스-n2-배열-자르기

나의 풀이

function solution(n, left, right) {
    const table = Array(n).fill().map(() => Array(n));
    const result = [];
    
    for(let i=0; i<n; i++) {
        for(let j=0; j<n; j++) {
            if(j-i <= 0) {
                table[i][j] = i+1;
            }  else {
                table[i][j] = table[i][j-1] + 1;
            }
        }
    }
    
    table.forEach(arr => result.push(...arr));
    
    return result.filter((v,i) => {
        if(i>= left && i<=right) return v;
    });
}

/*
채점 결과
정확성: 15.0
효율성: 0.0
합계: 15.0 / 50
*/

풀이 해설

주먹구구식문제에서 나온 방법대로 2차원 배열을 생성한 다음, 각 행을 이어 붙여서1차원화 한 다음 left ~ right의 숫자를 담아도 되겠지만,n은 무려 10^7까지 인풋으로 주어집니다.이 방법으론 시간과 공간 효율성에서 통과하지 못하겠네요.

좌표로 전환해서 생각문제 설명에서도, gif에서도 보이듯 아시겠지만 좌표 (r, c)에 들어갈 숫자는 max(r, c) + 1이 됩니다.그러면 left ~ right 범위의 숫자를 좌표로 변환만 해주면 문제가 쉽게 해결되겠네요.결론부터 말씀드리자면left ~ right범위의 임의의 숫자 num에 대해서 좌표 (r, c)를 구하는 공식은

입니다.이제 코드로 구현만 하면 됩니다.

function solution(n, left, right) {
    const ans = [];

    while (left <= right) {
        ans.push(Math.max(Math.floor(left / n), left++ % n) + 1);
    }

    return ans;
} 

후기

수학적 재능이 필요한걸까 ...