백준의 파티 문제를 풀면서 플로이드 워샬 알고리즘을 사용할 때 Math.max()
와 삼항연산자
의 차이에 대해 알게되었다.
메모리 | 시간 |
---|---|
36704 kb | 2796 ms |
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Boj_1238 {
static int INF = 1_000_000_000;
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
//BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = null;
st = new StringTokenizer(in.readLine(), " ");
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
int X = Integer.parseInt(st.nextToken()); // 파티장소
int[][] town = new int[N + 1][N + 1];
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (i != j)
town[i][j] = INF;
}
}
for (int i = 0; i < M; i++) {
st = new StringTokenizer(in.readLine(), " ");
int start = Integer.parseInt(st.nextToken());
int end = Integer.parseInt(st.nextToken());
int T = Integer.parseInt(st.nextToken());
town[start][end] = T;
}
for (int k = 1; k <= N; k++) {
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
int tmp = town[i][k] + town[k][j];
//삼항연산자 사용
town[i][j] = town[i][j] > tmp ? tmp : town[i][j];
//if문 사용
/*
if(town[i][j]>tmp){
town[i][j] = tmp;
}
*/
}
}
}
int answer = Integer.MIN_VALUE;
for (int i = 1; i <= N; i++) {
answer = answer < (town[i][X] + town[X][i]) ? (town[i][X] + town[X][i]) : answer;
}
System.out.println(answer);
}
}
메모리 | 시간 |
---|---|
24336 kb | 1328 ms |
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Boj_1238 {
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = null;
st = new StringTokenizer(in.readLine(), " ");
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
int X = Integer.parseInt(st.nextToken()); // 파티장소
int[][] town = new int[N + 1][N + 1];
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if(i!=j)
town[i][j] = 1000000;
}
}
for (int i = 0; i < M; i++) {
st = new StringTokenizer(in.readLine(), " ");
int start = Integer.parseInt(st.nextToken());
int end = Integer.parseInt(st.nextToken());
int T = Integer.parseInt(st.nextToken());
town[start][end] = T;
}
for (int k = 1; k <= N; k++) {
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
town[i][j] = Math.min(town[i][j],town[i][k]+town[k][j]);
}
}
}
int answer = Integer.MIN_VALUE;
for (int i = 1; i <= N; i++) {
answer = Math.max(town[i][X]+town[X][i], answer);
}
out.write(answer + "");
out.flush();
out.close();
in.close();
}
}
무려 시간이 반이나 줄었다.
그러나, 플로이드 워샬 알고리즘이 아닌 다른 데에서는 대부분 삼항연산자의 속도가 더 빠르다.(참고)
왜 플로이드 워샬 알고리즘에서는 삼항연산자에 비해 Math메서드의 속도가 더 빠른걸까?
Math.max()의 코드를 살펴보자
public final class Math{
private Math() {}
.
.
.
/**
* Returns the greater of two {@code int} values. That is, the
* result is the argument closer to the value of
* {@link Integer#MAX_VALUE}. If the arguments have the same value,
* the result is that same value.
*
* @param a an argument.
* @param b another argument.
* @return the larger of {@code a} and {@code b}.
*/
public static int max(int a, int b) {
return (a >= b) ? a : b;
}
/**
* Returns the smaller of two {@code int} values. That is,
* the result the argument closer to the value of
* {@link Integer#MIN_VALUE}. If the arguments have the same
* value, the result is that same value.
*
* @param a an argument.
* @param b another argument.
* @return the smaller of {@code a} and {@code b}.
*/
public static int min(int a, int b) {
return (a <= b) ? a : b;
}
.
.
.
}
... Math
의 메서드도 내부적으로 삼항연산자로 구현되어 있다.
진짜 왜일까......? JIT컴파일러? 최적화?
https://codeforces.com/blog/entry/80834
Java8버전에서는 시간 차이가 나고 Java11버전에서는 시간 차이가 나지 않고 거의 비슷했다.