N번째 큰 수
문제
N×N의 표에 수 N2개 채워져 있다. 채워진 수에는 한 가지 특징이 있는데, 모든 수는 자신의 한 칸 위에 있는 수보다 크다는 것이다. N=5일 때의 예를 보자.

이러한 표가 주어졌을 때, N번째 큰 수를 찾는 프로그램을 작성하시오. 표에 채워진 수는 모두 다르다.
입력
첫째 줄에 N(1 ≤ N ≤ 1,500)이 주어진다. 다음 N개의 줄에는 각 줄마다 N개의 수가 주어진다. 표에 적힌 수는 -10억보다 크거나 같고, 10억보다 작거나 같은 정수이다.
출력
첫째 줄에 N번째 큰 수를 출력한다.
-> 배열에서 정렬로 풀기
처음에는 쉽게 배열로 넣어서 정렬을 하면 되겠다고 생각을 하였다.
import java.io.*;
import java.util.*;
class Main {
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer stringTokenizer;
int number = Integer.parseInt(br.readLine());
int[] arr = new int[number * number];
int index = 0;
for(int i = 0 ; i < number; i++) {
stringTokenizer = new StringTokenizer(br.readLine());
for(int j=0; j < number; j++) {
arr[index++] = Integer.parseInt(stringTokenizer.nextToken());
}
}
Arrays.sort(arr);
System.out.println(arr[number*number - number]);
}
}
결과적으로 시간은 1648ms 시간이 나왔다.
여기서 더 시간을 줄여볼 수 없을 까? 라는 생각을 하였다.
-> 우선 순위 큐 사용하여 풀기
PriortyQueue로 풀어봤다.
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
PriorityQueue<Integer> pq = new PriorityQueue<>((o1, o2) -> o2-o1);
int N = Integer.parseInt(br.readLine());
for(int i=0;i<N;i++) {
st = new StringTokenizer(br.readLine());
for(int j=0;j<N;j++) {
pq.add(Integer.parseInt(st.nextToken()));
}
}
for(int i=0;i<N-1;i++) pq.poll();
System.out.println(pq.poll());
}
}
여기서 더 속도를 줄일 수 있을 까? 라고 생각하면서 검색을 해봤는데, peek로 더큰지 계산 후, 넣을 지 말지를 계산하는 방법이 있었다.
-> peek 사용
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
int n = Integer.parseInt(br.readLine());
PriorityQueue<Integer> pq = new PriorityQueue<Integer>();
st = new StringTokenizer(br.readLine());
for(int i=0; i<n; i++) {
int temp = Integer.parseInt(st.nextToken());
pq.offer(temp);
}
for(int i=1; i<n; i++) {
st = new StringTokenizer(br.readLine());
for(int j=0; j<n; j++) {
int temp = Integer.parseInt(st.nextToken());
if(pq.peek() < temp) {
pq.poll();
pq.offer(temp);
}
}
}
System.out.println(pq.poll());
}
}
peek()를 사용한 방법이 별로 시간의 변화를 많이 시켜주지는 않는것같았다.
-> QuickSelct 알고리즘 사용하기
우선 순위 큐를 사용하기 않고 QuickSelect 알고리즘을 사용하여 문제 풀기
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer stringTokenizer;
int number = Integer.parseInt(br.readLine());
int[] arr = new int[number * number];
int index = 0;
for(int i = 0 ; i < number; i++) {
stringTokenizer = new StringTokenizer(br.readLine());
for(int j=0; j < number; j++) {
arr[index++] = Integer.parseInt(stringTokenizer.nextToken());
}
}
System.out.println(quickSelect(arr, 0, arr.length-1, number-1));
}
private static int quickSelect(final int[] NUMS, int start, int end, int k) {
if (start <= end) {
int pivot = partition(NUMS, start, end);
if (pivot == k) {
return NUMS[k];
}
else if (pivot > k) {
return quickSelect(NUMS, start, pivot - 1, k);
}
else {
return quickSelect(NUMS, pivot + 1, end, k);
}
}
return Integer.MIN_VALUE;
}
private static int partition(final int[] NUMS, int start, int end) {
int pivot = start + new Random().nextInt(end - start + 1);
swap(NUMS, end, pivot);
for (int i = start; i < end; i++) {
if (NUMS[i] > NUMS[end]) {
swap(NUMS, i, start);
start++;
}
}
swap(NUMS, start, end);
return start;
}
private static void swap(final int[] nums, final int aIdx, final int bIdx) {
int tmp = nums[aIdx];
nums[aIdx] = nums[bIdx];
nums[bIdx] = tmp;
}
}
시간적으로 제일 빠르게 해결이 가능하다.
'코딩테스트' 카테고리의 다른 글
[코딩 테스트] leet code 6. Zigzag Conversion (0) | 2022.09.09 |
---|---|
[프로그래머스] - 가장 큰 수 (0) | 2022.09.03 |
[코딩테스트] 프로그래머스 - 스킬트리 (0) | 2022.06.16 |