https://www.acmicpc.net/problem/2075
코드설명
정렬(Sort) + 우선순위큐(PriorityQueue) 를 활용합니다.
문제에서 주어진 소개와는 상관없이, 다른 효과적인 방법을 찾아내야 한다는 점에서 좋은 문제라고 생각합니다.
문제에서 표의 채워진 수에 한 가지 특징이 있다, 모든 수는 자신의 한 칸 위에 있는 수보다 크다는 것 이다. 라는 문구를 보면, 문제에서 뭔가 이러한 특징을 사용해야만 풀 수 있을 것 같이 느껴집니다.
그렇기에, 처음에는 시작점을 기준으로 뭔가 규칙이 있는건가? 찾아보게 되고,,,
아니면 숫자의 수 총 20억개를 다 만들어서 dp로 저장해야하나? (이 부분은 메모리제한 12MB 이기 떄문에 안됩니다.)
아니면 동적계획법으로, 시작위치에서 아래 위치까지 증가하는 부분 수열 문제인가? (이 부분은 각 열들이 서로 정렬되어있지 않기에 불가합니다.)
1500x1500 개의 map을 다 도면서 각 위치마다 나보다 큰 수가 Map에 몇개인지 구해서 그것이 N개일경우 중단하나? 라는 생각도 듭니다. 나보다 큰 수의 개수가 곧 내가 몇번쨰 N번쨰 수인지 알 수 있으니까요. (1500x1500x1500 = 10^6 * 15^3.. 연산개수를 보면, 시간초과가 나는 것을 알 수 있습니다. )
처음에, 어렵게 생각해서 고민했지만 아이디어만 떠오른다면 쉬운 문제였습니다.(아이디어 떠오르는것이 사실 가장 어렵습니다)
Arrays.sort가 아닌 PriorityQueue를 활용하여 pop을 N번 하도록 만들어도 가능합니다.
N(1 ≤ N ≤ 1,500)의 범위가 작기에 Arrays.sort로 정렬을 한뒤 진행하면됩니다.
Arrays.sort의 정렬 시간복잡도는 평균적으로는 O(N log (N) ) 이고, 최악의 경우 O(N^2) 입니다.
PriorityQueue 의 삽입 삭제 시간복잡도는 O(log N)의 시간이 걸립니다.
PriorityQUeue의 정렬은 O(N log N) 입니다.
우선순위큐를 활용하여 진행하는것이 빠를 것 입니다.확인결과 시간은 우선순위큐를 활용한 코드의 시간이 1.8배 빨랐습니다.
코드
단순히 정렬을 사용하여 진행
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
public static int N;
public static int idx = 0;
public static int answer = 0;
public static int[] arr;
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
arr = new int[N*N];
for(int i=0;i<N;i++) {
st = new StringTokenizer(br.readLine());
for(int j=0;j<N;j++) {
arr[idx++] = Integer.parseInt(st.nextToken());
}
}
Arrays.sort(arr);
System.out.println(arr[N*N - N]);
}
}
우선순위큐를 활용하여 진행
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
public static int N;
public static int idx = 0;
public static int answer = 0;
public static int[] arr;
public static PriorityQueue<Node> pq = new PriorityQueue<>();
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
for(int i=0;i<N;i++) {
st = new StringTokenizer(br.readLine());
for(int j=0;j<N;j++) {
pq.offer(new Node(Integer.parseInt(st.nextToken())));
}
}
for(int i=0;i<N-1;i++) {
pq.poll();
}
System.out.println(pq.poll().value);
}
}
class Node implements Comparable<Node>{
int value;
public Node(int value) {
this.value = value;
}
@Override
public int compareTo(Node other) {
if(this.value < other.value) {
return 1;
}else if(this.value > other.value){
return -1;
}else {
return 0;
}
}
}
우선순위큐에 Collections.reverserOrder()를 사용하면 간단하게 내림차순으로 구현이 가능하다.
package Main;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class Main {
public static int C, N, H, W, K;
public static int answer = 0;
public static int[][] matrix;
public static PriorityQueue<Integer> pq = new PriorityQueue<>(Collections.reverseOrder());
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
matrix = new int[N][N];
for(int i=0;i<N; i++) {
st = new StringTokenizer(br.readLine());
for(int j=0;j<N; j++) {
matrix[i][j] = Integer.parseInt(st.nextToken());
pq.add(matrix[i][j]);
}
}
while(!pq.isEmpty() && N - 1 > 0) {
pq.poll();
N-=1;
}
System.out.println(pq.poll());
}
}
'알고리즘 > 백준' 카테고리의 다른 글
[백준] 17615 볼 모으기 - 구현 + 그리디 JAVA (0) | 2023.08.09 |
---|---|
[백준] 1138 한 줄로 서기 - 구현(Implementation) + 그리디(Greedy, 탐욕법) + 아이디어 JAVA (0) | 2023.08.09 |
[백준] 2304 창고 다각형 - 구현 + 그리디 JAVA (0) | 2023.08.08 |
[백준] 5397 키로거 - 연결리스트 + 링크드리스트 JAVA (0) | 2023.08.08 |
[백준] 1406 에디터 - 연결리스트 + 링크드리스트 JAVA (0) | 2023.08.08 |