지난포스트 (deprecated)/Algorithm & Data Structure (deprecated)

[정렬] K번째 수 with JS - Lv1

.log('FE') 2018. 12. 18. 11:53
728x90
반응형

* 프로그래머스 코딩테스트 연습 > 정렬 > K번째 수

 

문제 설명

 

배열 array의 i번째 숫자부터 j번째 숫자까지 자르고 정렬했을 때, k번째에 있는 수를 구하려 합니다.

예를 들어 array가 [1, 5, 2, 6, 3, 7, 4], i = 2, j = 5, k = 3이라면

 

1. array의 2번째부터 5번째까지 자르면 [5, 2, 6, 3]입니다.
2. 1에서 나온 배열을 정렬하면 [2, 3, 5, 6]입니다.
3. 2에서 나온 배열의 3번째 숫자는 5입니다.


배열 array, [i, j, k]를 원소로 가진 2차원 배열 commands가 매개변수로 주어질 때, commands의 모든 원소에 대해 앞서 설명한 연산을 적용했을 때 나온 결과를 배열에 담아 return 하도록 solution 함수를 작성해주세요.

 

입출력 예

 

array = [1, 5, 2, 6, 3, 7, 4]

commands = [[2, 5, 3], [4, 4, 1]. [1, 7, 3]]

return = [5, 6, 3]

 

입출력 예 설명

 

[1, 5, 2, 6, 3, 7, 4]를 2번째부터 5번째까지 자른 후 정렬합니다. [2, 3, 5, 6]의 세 번째 숫자는 5입니다.
[1, 5, 2, 6, 3, 7, 4]를 4번째부터 4번째까지 자른 후 정렬합니다. [6]의 첫 번째 숫자는 6입니다.
[1, 5, 2, 6, 3, 7, 4]를 1번째부터 7번째까지 자릅니다. [1, 2, 3, 4, 5, 6, 7]의 세 번째 숫자는 3입니다.

 

 


 

 

Step 1. 테스트케이스 작성 - array 인자만 사용

 

우선 어떻게 하면 입출력 예의 설명 처럼 나올지 딱 하나의 케이스만 적용해서 코드를 짰습니다.

 

var array = [1, 5, 2, 6, 3, 7, 4];
var commands = [[2, 5, 3], [4, 4, 1], [1, 7, 3]];


function solution(array, commands) {
let filter = array.slice(1, 5); // [5, 2, 6, 3]
let sorted = filter.sort(); // [2, 3, 5, 6]
return sorted[2];
}


console.log(solution(array, commands)) // 5



- 주어진 배열을 slice(start, end) 를 활용하여 filter 에 새 배열로 저장합니다.

- [2, 5, 3] 케이스를 활용했는데 1 부터 시작한 이유는 배열은 첫 시작 index 가 0부터 시작하기 때문입니다.

- sort() 로 따로 뽑아낸 배열을 정렬하고

- 3번째 값인 5를 출력하기위해서 index 번호인 2를 넣어서 출력합니다.

 

 

Step 2. 테스트케이스 작성 - 두개의 인자 모두 사용

 

Step1 에서는 array 인자만 사용해서 직접 숫자를 입력해서 출력했지만 실제 해야하는건 solution 내부에 있는 숫자들은 commands의 중첩 배열의 값이 들어가야 합니다.

 

array 와 다르게 commands 는

 

commands[0] // [2, 5, 3]

commands[0][0] // 2

 

주어진 문제에서 [i, j, k] 로 표현을 했고 그럼 각각 변수를 만들어 해당값이 들어가도록 하겠습니다.

 

var array = [1, 5, 2, 6, 3, 7, 4];
var commands = [[2, 5, 3], [4, 4, 1], [1, 7, 3]];


function solution(array, commands) {
let i = commands[0][0]; // 2
let j = commands[0][1]; // 5
let k = commands[0][2]; // 3


let filter = array.slice(i-1, j);
let sorted = filter.sort();
return sorted[k-1];
}


console.log(solution(array, commands)) // 5

 

- 각각의 i, j, k 변수에 해당하는 값이 들어가도록하고

- 직접 숫자를 넣어줬던 부분에는 변수를 활용하여 값을 넣어 주었습니다.

 

 

Step 3. 확장적용

 

이제 필요한것을 확장적용입니다. commands 에는 값을 3개가진 배열을 3개 갖고있습니다. Step2 의 테스트케이스는 그중 첫번째 배열에 대해서만 적용이 가능하기때문에 나머지 두개의 배열도 solution 함수 내부에서 적용되도록 만들어야 합니다.

 

전체배열을 순회하면서 i, j, k 변수에 값을 저장하도록 만들면 될것같습니다.

 

var array = [1, 5, 2, 6, 3, 7, 4];
var commands = [[2, 5, 3], [4, 4, 1], [1, 7, 3]];


function solution(array, commands) {


let result = [];


for(let a = 0; a < commands.length; a++) {
let i = commands[a][0];
let j = commands[a][1];
let k = commands[a][2];

 

let filter = array.slice(i-1, j);
let sorted = filter.sort();

 

result.push(sorted[k-1]);
}


console.log(result)
}


solution(array, commands) // [5, 6, 3];

 

 

- 실제 출력해야 할 결과물은 각각의 K 번째에 해당하는 값의 배열을 출력해야하므로

- 결과를 출력할 빈 배열 result 를 만들어 줍니다.

- for 문으로 commands 의 배열의 갯수만큼 반복실행 하도록하였고

- i, j, k 에는 반복실행 할 때 마다 각각의 해당 값이 저장되도록 하였습니다.

- 그 밑에 filter 와 sorted 는 동일하고

- result 에 값을 저장하기위해 push 를 사용했습니다.

- for문 내부에서 push를 해 주어야 모든값이 저장됩니다.

- for문 바깥에서 push 했을경우 가장 마지막 값만 저장됩니다.

 

 

결과 확인

 

 

 

일단 실행결과는 테스트를 통과했습니다.

 

 

 

그러나 코드채점을 해보니 테스트2 에서 실패가 떴네요 각각의 테스트가 뭘 테스트하는거고 뭘 의미하는건지는 모르겠습니다.

 

일단 실패가 떴으니 어떤걸 수정하고 고쳐볼 수 있을지 고민해 보겠습니다.

 

 

 

Step 4. 수정

 

sort() 함수가 문제였던것같습니다. sort() 로 숫자를 정렬할 경우 예를들면 [21, 30, 1, 4] 가있다면

 

[21, 30, 1, 4] .sort() // [1, 21, 30, 4]

 

이렇게 정렬된다고 합니다. 기본정렬순서는 문자열의 유니코드 포인트를 따른다고 MDN 에 정의되어있습니다.

 

따라서 숫자를 비교하기위해서는

 

 

    let
sorted = filter.sort((a, b) => a - b);

 

 

이러한 형태로 정렬해야 정상적으로 숫자의 정렬이 이루어 집니다.

 

이부분을 수정하니 정상적으로 모든 테스트의 통과가 이루어 졌습니다.

 

 

Step 5. 리팩토링

 

의식의 흐름대로 그리고 보기 편하도록 코드를 작성하였는데 이걸 좀더 코드라인을 줄이기 위한 리팩토링 작업을 해보겠습니다.

 

function solution(array, commands) {
return commands.map(arr => {
console.log(arr);
// [2, 5, 3]
// [4, 4, 1]
// [1, 7, 3]
});
}

 

map() 메서드는 배열내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환합니다. - MDN

 

즉 arr 을 출력하면 2차원 배열에서 1차원 배열로 만들 수 있고 그럼 저 map 함수 내부에서 최종으로 출력할 값이 나오도록 작성해 주면 됩니다.

 

function solution(array, commands) {
return commands.map(arr => {
return array.slice(arr[0] - 1, arr[1]).sort((a, b) => a - b)
});
}

 

아까 여러줄로 나눠서 변수를 만들어 저장해 주었던 값들을 정렬까지 한꺼번에 처리합니다.

 

// [2, 3, 5, 6]

// [6]

// [1, 2, 3, 4, 5, 6, 7]

 

이라는 값들이 반환되었고 이제 K 번째의 숫자를 찾는 코드만 작성해주면됩니다.

 

function solution(array, commands) {
return commands.map(arr => {
return array.slice(arr[0] - 1, arr[1])
.sort((a, b) => a - b)
.slice(arr[2] - 1, arr[2])[0]
});
}

 

마지막에 [0] 이 들어간 이유는 slice 해서 나온값들은 하나지만 여전히 배열에 속해있기 때문에 중첩배열이 아닌 단일배열로 최종 출력하려면 index[0] 번째 값을 가져야 숫자만 정상적으로 출력이 됩니다. 

 

사실 실제 코드 처리부분은 한줄로 처리한것이나 마찬가지인데 코드작성자가 아닌 다른사람이 봤을때도 저게 충분히 가독성과 효율성을 모두 챙길수 있는 코드인지는 한번 생각해볼 필요가 있을것 같습니다.

 

 

code-reading 블로그에 방문해 주셔서 환영합니다.
댓글은 모두 환영하니 많이 달아주세요.

 

728x90
반응형