ALGORITHM NOTE1

BOJ 18870 - 좌표 압축

좌표를 줄이자!

#algorithm#boj#silver#sorting
아카이브로 돌아가기

문제 링크

문제

수직선 위에 NN개의 좌표 X1X_1, X2X_2, ..., XNX_N이 있다. 이 좌표에 좌표 압축을 적용하려고 한다.

XiX_i를 좌표 압축한 결과 XiX'_i의 값은 Xi>XjX_i > X_j를 만족하는 서로 다른 좌표 XjX_j의 개수와 같아야 한다.

X1X_1, X2X_2, ..., XNX_N에 좌표 압축을 적용한 결과 X1X'_1, X2X'_2, ..., XNX'_N를 출력해보자.

입력

첫째 줄에 N이 주어진다.

둘째 줄에는 공백 한 칸으로 구분된 X1X_1, X2X_2, ..., XNX_N이 주어진다.

출력

첫째 줄에 X1X'_1, X2X'_2, ..., XNX'_N을 공백 한 칸으로 구분해서 출력한다.

풀이

값 자체의 크기는 중요하지 않고, 정렬했을 때 몇 번째로 작은 값인지가 중요하다. 그래서 중복을 제거한 뒤 정렬 순서를 새 번호로 붙이면 된다.

코드에서는 원본 배열을 하나 보관해 두고, 복사본을 정렬한 뒤 고유한 값마다 압축된 번호를 매핑한다. 이후 원본 순서대로 맵을 조회해 출력하면 된다.

결국 정렬과 매핑을 한 번 해 두면 이후 출력은 단순 조회만 남는다. 좌표 압축은 값을 줄인다기보다 순서만 남긴다고 이해하는 편이 좋다.

코드

cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
 
void solve() {
	int N, n;
	cin >> N;
 
	vector<int> vec, coord;
 
	for (int i = 0; i < N; i++) {
		cin >> n;
		vec.push_back(n);
		coord.push_back(n);
	}
 
	sort(vec.begin(), vec.end());
	vec.erase(unique(vec.begin(), vec.end()), vec.end());
 
	for (int j = 0; j < N; j++) {
		cout << lower_bound(vec.begin(), vec.end(), coord[j]) - vec.begin() << " ";
	}
}
 
int main() {
 
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
 
	solve();
 
	return 0;
}

복잡도

  • 시간 복잡도: 좌표를 정렬하고 압축 값을 매핑하므로 O(NlogN)O(N \log N)이다.
  • 공간 복잡도: 좌표 배열과 압축 결과를 저장하므로 O(N)O(N)이다.

마무리

값을 줄이는 문제가 아니라 정렬 순서의 번호만 다시 매긴다고 보면 좌표 압축이 훨씬 쉽다.