정렬(Sorting) 알고리즘 문제풀이

Minji Lee·2023년 11월 9일
0

JS코딩테스트

목록 보기
28/122
post-thumbnail

JS 정렬 라이브러리

sort() 함수

  • 시간 복잡도: O(NlogN)
  • sort() 함수 사용 제한된다면, 병합 정렬과 같은 알고리즘 직접 구현하여 사용
  • 배열.sort(compareFunction);
    • compareFunction: 정렬 기준을 정해주는 함수
    • 내림차순, 오름차순 등 구체적인 정렬 기준 설정 가능
    • 두 개의 원소 a, b를 입력 받음
      1. 반환 값이 0보다 작은 경우 → a가 우선순위가 높아, 앞에 위치(오름차순)
      2. 반환 값이 0보다 큰 경우 → b가 우선순위가 높아, 앞에 위치(내림차순)
      3. 반환 값이 0인 경우 → a와 b의 순서를 변경하지 않음
    • 정렬 기준함수 사용하지 않는 경우, 각 원소는 문자열로 취급! → 유니코드 값 순서대로 정렬

ex) 오름차순 정렬 예시

// 1번
let arr = [1, 8, 5, 9, 21, 3, 7, 2, 15];

function compare(a,b){
	if(a<b) return -1;
	else if(a>b) return 1;
	else return 0;
}
arr.sort(compare);
console.log(arr);
// [1, 2, 3, 5, 7, 8, 9, 15, 21]
// 2번
let arr = [1, 8, 5, 9, 21, 3, 7, 2, 15];

function compare(a,b){
	return a-b;
}
arr.sort(compare);
console.log(arr);
// [1, 2, 3, 5, 7, 8, 9, 15, 21]
// 3번
let arr = [1, 8, 5, 9, 21, 3, 7, 2, 15];
arr.sort(function (a,b) {
	return a-b;
});
console.log(arr);
// [1, 2, 3, 5, 7, 8, 9, 15, 21]

ex) 내림차순 정렬 예시

let arr = [1, 8, 5, 9, 21, 3, 7, 2, 15];
arr.sort(function (a,b) {
	return b-a;
});
console.log(arr);
// [21, 15, 9, 8, 7, 5, 3, 2, 1]

ex) 문자열에 대한 오름차순 정렬 → 유니코드 순으로 정렬

let arr = ['fineapple', 'banana', 'durian', 'apple', 'carrot'];
arr.sort(function (a,b) {
	return a-b;
});
console.log(arr);
// ['apple', 'banana', 'carrot', 'durian', 'fineapple']

ex) 객체에 대하여 원하는 기준으로 오름차순 정렬

let arr = [
	{ name: "홍길동", score: 90 },
	{ name: "김철수", score: 85 },
	{ name: "박영희", score: 97 }
];

arr.sort(function (a,b) {
	return b.score-a.score;
});
console.log(arr);
/* 
[
	{ name: "박영희", score: 97 },
	{ name: "홍길동", score: 90 },
	{ name: "김철수", score: 85 }
]
*/

정렬 문제 풀이

1. 세수 정렬(2752)

문제

동규는 세수를 하다가 정렬이 하고 싶어졌다. 정수 세 개를 생각한 뒤에, 이를 오름차순으로 정렬하고 싶어졌다. 정수 세 개가 주어졌을 때, 가장 작은 수, 그 다음 수, 가장 큰 수를 출력하는 프로그램을 작성하시오.

입력

정수 세 개가 주어진다. 이 수는 1보다 크거나 같고, 1,000,000보다 작거나 같다. 이 수는 모두 다르다.

출력

제일 작은 수, 그 다음 수, 제일 큰 수를 차례대로 출력한다.

작성한 코드

let fs = require("fs");
let input = fs.readFileSync("/dev/stdin").toString().split("\n");

let answer = "";

let numbers = input[0]
  .split(" ")
  .map(Number)
  .sort((a, b) => a - b);

numbers.map((number) => (answer += number + " "));
console.log(answer);

2. 수 정렬하기(2750)

문제

N개의 수가 주어졌을 때, 이를 오름차순으로 정렬하는 프로그램을 작성하시오.

입력

첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000)이 주어진다. 둘째 줄부터 N개의 줄에는 수가 주어진다. 이 수는 절댓값이 1,000보다 작거나 같은 정수이다. 수는 중복되지 않는다.

출력

첫째 줄부터 N개의 줄에 오름차순으로 정렬한 결과를 한 줄에 하나씩 출력한다.

작성한 코드

let fs = require("fs");
let input = fs.readFileSync("/dev/stdin").toString().split("\n");

let N = Number(input[0]); // 수의 개수(1 ≤ N ≤ 100,000)
let numbers = []; // N개의 수를 담을 배열

for (let i = 1; i <= N; i += 1) {
  numbers.push(Number(input[i]));
}

numbers.sort((a, b) => a - b); // 오름차순 정렬
let result = "";
numbers.map((number) => (result += number + "\n"));
console.log(result);

3. K번째 수(11004)

문제

수 N개 A1, A2, ..., AN이 주어진다. A를 오름차순 정렬했을 때, 앞에서부터 K번째 있는 수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N(1 ≤ N ≤ 5,000,000)과 K (1 ≤ K ≤ N)이 주어진다.

둘째에는 A1, A2, ..., AN이 주어진다. (-109 ≤ Ai ≤ 109)

출력

A를 정렬했을 때, 앞에서부터 K번째 있는 수를 출력한다.

작성한 코드

let fs = require("fs");
let input = fs.readFileSync("/dev/stdin").toString().split("\n");

let [N, K] = input[0].split(" ").map(Number);

let arr = input[1].split(" ").map(Number);
arr.sort((a, b) => a - b); // 오름차순 정렬
console.log(arr[K - 1]); // K번째 수 출력(인덱스가 0부터 시작하므로 -1해주어야 함)

4. 좌표 정렬하기(11650)

문제

2차원 평면 위의 점 N개가 주어진다. 좌표를 x좌표가 증가하는 순으로, x좌표가 같으면 y좌표가 증가하는 순서로 정렬한 다음 출력하는 프로그램을 작성하시오.

입력

첫째 줄에 점의 개수 N (1 ≤ N ≤ 100,000)이 주어진다. 둘째 줄부터 N개의 줄에는 i번점의 위치 xi와 yi가 주어진다. (-100,000 ≤ xi, yi ≤ 100,000) 좌표는 항상 정수이고, 위치가 같은 두 점은 없다.

출력

첫째 줄부터 N개의 줄에 점을 정렬한 결과를 출력한다.

작성한 코드

let fs = require("fs");
let input = fs.readFileSync("/dev/stdin").toString().split("\n");

let N = Number(input[0]); // 점의 개수
let dots = [];
// 점들 객체에 넣기
for (let i = 1; i <= N; i += 1) {
  let dot = input[i].split(" ").map(Number);
  dots.push({ x: dot[0], y: dot[1] });
}

// 첫번째 조건: x좌표 오름차순 정렬, 두번째 조건: y좌표 오름차순 정렬
dots.sort((a, b) => a.x - b.x || a.y - b.y);

let result = "";
dots.map((dot) => (result += dot.x + " " + dot.y + "\n"));
console.log(result);

5. 단어 정렬(1181)

문제

알파벳 소문자로 이루어진 N개의 단어가 들어오면 아래와 같은 조건에 따라 정렬하는 프로그램을 작성하시오.
1. 길이가 짧은 것부터
2. 길이가 같으면 사전 순으로
단, 중복된 단어는 하나만 남기고 제거해야 한다.

입력

첫째 줄에 단어의 개수 N이 주어진다. (1 ≤ N ≤ 20,000) 둘째 줄부터 N개의 줄에 걸쳐 알파벳 소문자로 이루어진 단어가 한 줄에 하나씩 주어진다. 주어지는 문자열의 길이는 50을 넘지 않는다.

출력

조건에 따라 정렬하여 단어들을 출력한다.

작성한 코드

let fs = require("fs");
let input = fs.readFileSync("/dev/stdin").toString().split("\n");

let N = Number(input[0]); // 단어의 개수
let wordSet = new Set();
// 단어들 집합에 넣기(중복 제거)
for (let i = 1; i <= N; i += 1) {
  wordSet.add(input[i]);
}

// 집합을 배열로 변환
let words = Array.from(wordSet);
// 1번째 조건: 길이가 짧은 것부터, 2번째 조건: 사전 순으로 정렬(localeCompare 이용)
words.sort((a, b) => a.length - b.length || a.localeCompare(b));

let result = "";
words.map((word) => (result += word + "\n"));
console.log(result);

💡 문자열.prototype.localeCompare() 메서드
사용법: string.localeCompare(compareString)</span>
: string 문자열이 정렬 순서에 따라 주어진 문자열보다 앞에 오는지, 뒤에 오는지 여부를 나타내는 숫자 반환

  • 문자열이 compareString 이전에 정렬된 경우: -1
  • 동일한 경우: 0
  • 이후에 정렬된 경우: 1

6. 좌표 압축(18870)

문제

수직선 위에 N개의 좌표 X1, X2, ..., XN이 있다. 이 좌표에 좌표 압축을 적용하려고 한다.
Xi를 좌표 압축한 결과 X'i의 값은 Xi > Xj를 만족하는 서로 다른 좌표 Xj의 개수와 같아야 한다.
X1, X2, ..., XN에 좌표 압축을 적용한 결과 X'1, X'2, ..., X'N를 출력해보자.

입력

첫째 줄에 N이 주어진다.

둘째 줄에는 공백 한 칸으로 구분된 X1, X2, ..., XN이 주어진다.

출력

첫째 줄에 X'1, X'2, ..., X'N을 공백 한 칸으로 구분해서 출력한다.

작성한 코드 → 시간 초과 발생

: indexOf로 인해 시간복잡도가 O(n2)n^2)가 됨

let fs = require("fs");
let input = fs.readFileSync("/dev/stdin").toString().split("\n");

let XofList = input[1].split(" ").map(Number);
let copyXofList = [...new Set(XofList)]; // 중복 제거한 집합을 배열로 변환
copyXofList.sort((a, b) => a - b); // 오름차순으로 정렬
result = "";

// XofList의 원소를 순회하면서 오름차순 정렬된 인덱스 값 반환(=> 자신보다 작은 원소의 개수와 같음)
XofList.forEach((x) => {
  result += copyXofList.indexOf(x) + " ";
});

console.log(result);

참고한 코드Map 이용

let fs = require("fs");
let input = fs.readFileSync("/dev/stdin").toString().split("\n");

let XofList = input[1].split(" ").map(Number);
let copyXofList = [...new Set(XofList)]; // 중복 제거한 집합을 배열로 변환
copyXofList.sort((a, b) => a - b); // 오름차순으로 정렬

// 0부터 차례대로 매핑
let myMap = new Map();
for (let i=0;i<copyXofList.length; i+=1){
	myMap.set(copyXofList[i], i);
}

result = "";
XofList.forEach((x) => {
  result += myMap.get(x)+ " ";
});

console.log(result);

7. 나이순 정렬(10814)

문제

온라인 저지에 가입한 사람들의 나이와 이름이 가입한 순서대로 주어진다. 이때, 회원들을 나이가 증가하는 순으로, 나이가 같으면 먼저 가입한 사람이 앞에 오는 순서로 정렬하는 프로그램을 작성하시오.

입력

첫째 줄에 온라인 저지 회원의 수 N이 주어진다. (1 ≤ N ≤ 100,000)

둘째 줄부터 N개의 줄에는 각 회원의 나이와 이름이 공백으로 구분되어 주어진다. 나이는 1보다 크거나 같으며, 200보다 작거나 같은 정수이고, 이름은 알파벳 대소문자로 이루어져 있고, 길이가 100보다 작거나 같은 문자열이다. 입력은 가입한 순서로 주어진다.

출력

첫째 줄부터 총 N개의 줄에 걸쳐 온라인 저지 회원을 나이 순, 나이가 같으면 가입한 순으로 한 줄에 한 명씩 나이와 이름을 공백으로 구분해 출력한다.

작성한 코드

let fs = require("fs");
let input = fs.readFileSync("/dev/stdin").toString().split("\n");

let N = Number(input[0]); // 온라인 저지 회원 수

let members = [];

for (let i = 1; i <= N; i += 1) {
  let member = input[i].split(" ");
	// index는 가입한 순서를 저장하기 위해 사용
  members.push({ index: i, age: Number(member[0]), name: member[1] });
}

// 1번째 조건: 나이 어린 순부터, 2번째 조건: 먼저 가입한 순부터
members.sort((a, b) => a.age - b.age || a.index - b.index);

let result = "";
members.map((member) => (result += member.age + " " + member.name + "\n"));
console.log(result);

8. 소트인사이드(1427)

문제

배열을 정렬하는 것은 쉽다. 수가 주어지면, 그 수의 각 자리수를 내림차순으로 정렬해보자.

입력

첫째 줄에 정렬하려고 하는 수 N이 주어진다. N은 1,000,000,000보다 작거나 같은 자연수이다.

출력

첫째 줄에 자리수를 내림차순으로 정렬한 수를 출력한다.

작성한 코드

let fs = require("fs");
let input = fs.readFileSync("/dev/stdin").toString().split("\n");

let number = input[0].split("").map(Number);
number = number.sort((a, b) => b - a).join("");
console.log(number);

0개의 댓글