문제
https://www.acmicpc.net/problem/18870
18870번: 좌표 압축
수직선 위에 N개의 좌표 X1, X2, ..., XN이 있다. 이 좌표에 좌표 압축을 적용하려고 한다. Xi를 좌표 압축한 결과 X'i의 값은 Xi > Xj를 만족하는 서로 다른 좌표의 개수와 같아야 한다. X1, X2, ..., XN에 좌
www.acmicpc.net
풀이
1. HashMap을 이용하여 풀 경우
원본 배열에 대해서 정렬한다.
정렬한 배열에 hashMap에 추가하면서 value를 증가시킨다. 이때 기존의 HashMap에 key 값이 있는지 확인하고 없을 경우에만 value를 증가시킨다.
(문제 예시를 예로들어 보자면, arr = {2, 4, -10, 4, -9} 를 정렬하면 {-10, -9, 2, 4, 4} 가 된다.
이 정렬된 배열에 대해 hashMap에 추가하면서 value를 증가시킨다.
예를 들어 가장 낮은 값인 -10이 0이 될 것이다. 그 다음 -9가 1 .. 이런식으로 말이다. )
2. 이분탐색을 이용하여 풀 경우
원본 배열에 대해 정렬한다.
정렬한 배열에서 중복을 제거한다.
중복 제거한 배열에 대해 이분탐색을 진행하여 index를 구한다.
두 경우다 주의해야 할것은 출력은 StringBuilder로 해야 시간 초과가 안난다는 점이다.
코드
1. HashMap
import java.util.*;
import java.io.*;
public class Main {
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
StringBuilder sb = new StringBuilder();
int n = Integer.parseInt(br.readLine());
int arr [] = new int [n];
int sorted [] = new int [n];
HashMap<Integer, Integer> map = new HashMap<>();
st = new StringTokenizer(br.readLine());
for(int i=0;i<n;i++) {
arr[i] = Integer.parseInt(st.nextToken());
sorted[i] = arr[i];
}
Arrays.sort(sorted);
int idx = 0;
for(int i=0;i<n;i++) {
if(!map.containsKey(sorted[i]))
map.put(sorted[i], idx++);
}
for(int i=0;i<n;i++) {
sb.append(map.get(arr[i]) + " ");
}
System.out.print(sb);
}
}
2. 이분탐색
import java.util.*;
import java.io.*;
public class Main {
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
StringBuilder sb = new StringBuilder();
int n = Integer.parseInt(br.readLine());
st = new StringTokenizer(br.readLine());
int arr [] = new int [n];
int temp [] = new int [n];
for(int i=0;i<n;i++) {
arr[i] = Integer.parseInt(st.nextToken());
temp[i] = arr[i];
}
Arrays.sort(temp);
ArrayList<Integer> list = new ArrayList<>();
list.add(temp[0]);
for(int i=1;i<n;i++) {
if(temp[i-1] != temp[i]) {
list.add(temp[i]);
}
}
for(int i = 0; i < n; i++) {
sb.append(binarySearch(arr[i], list)+" ");
}
System.out.print(sb);
}
static int binarySearch(int val, ArrayList<Integer> list) {
int s = 0;
int e = list.size() - 1;
while(s <= e) {
int mid = (s + e) / 2;
if(list.get(mid) < val) {
s = mid+1;
}
else if(list.get(mid) > val) {
e = mid-1;
}
else {
return mid;
}
}
return -1;
}
}