프로그래밍/알고리즘

no.18870 좌표 압축

데일리 백수 2025. 1. 21. 20:40
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <cmath>
using namespace std;


int main()
{

	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int N;
	cin >> N;
	vector<int > v(N);

	for (int i = 0; i < N; i++) {
		cin >> v[i];
	}

	vector<int> sorted = v;
	sort(sorted.begin(), sorted.end());
	sorted.erase(unique(sorted.begin(), sorted.end()), sorted.end());

	for (int i = 0; i < N; i++) {
		cout << lower_bound(sorted.begin(), sorted.end(), v[i]) - sorted.begin() << ' ';
	}

	return 0;
}

 

문제분석 

맨 처음에는 set을 받아서 풀면되는건가? 라는 생각을 했지만 

sort와 algorithm 헤더에 포함된 메소드들로 풀 수 있다는 사실을 파악했다. 

 

sort(sorted.begin(), sorted.end())

  • 헤더: <algorithm>
  • 동작: sort는 [first, last) 구간을 오름차순 정렬한다

sorted 벡터 전체 구간에 대한 정렬을 진행한다. 

정렬 후, 동일 원소들이 연속 위치하게 된다 

 

unique(sorted.begin(), sorted.end())

  • 헤더: <algorithm>
  • 동작: 연속된 중복 원소를 제거하고, 중복이 없는 상태를 만들기 위한 “새로운 끝” 이터레이터를 반환.
    • 실제로 컨테이너 크기를 줄이지 않고, “중복 아닌” 원소들을 앞에 모으고, 뒤쪽에 불필요한 원소가 남아있도록 정리만 함.
    • 반환 값으로는 중복이  제거된 유효구간 끝을 가르키는 이터레이터를 반환함 

따라서 unique한 값을 sorted.erase 메소드를 이용하여 물리적으로 제거해주어야함 

 

sorted.erase(unique(sorted.begin(), sorted.end()), sorted.end());

 

즉 이코드는 유니크 값을 이용하여 sorted 배열을 정리한 후, 반환 이터레이터, 즉 유효구간 끝에서 벡터 끝까지 지워주게됨

중복된 값들이 사라진다. 

 

lower_bound(sorted.begin(), sorted.end(), v[i])

  • 헤더: <algorithm>
  • 동작: 이진 탐색으로, [first, last) 구간에서 정렬된 상태를 가정하에, “v[i] 이상이 처음 나타나는 위치”(이터레이터)를 찾는다.

정렬 + 중복이 제거된 sorted에서 v[i] 인덱스가 몇번쨰 인덱스인지 찾기 위해 사용한다.

반환 값으로는 이터레이터가 오기 때문에, 인덱스를 얻기 위해서는 해당 이터레이터가 컨테이너의 시작 

즉 sorted.begin으로부터 몇번째 떨어져 있는지를 계산해야함

 

인덱스를 구하려면 꼭 -sorted.begin이 필요함!

'프로그래밍 > 알고리즘' 카테고리의 다른 글

no.1697 숨바꼭질  (0) 2025.01.24
no.7576 토마토  (0) 2025.01.21
no.2630 색종이 만들기  (0) 2025.01.20
no.1927 최소 힙  (0) 2025.01.20
no.1389 케빈 베이컨의 6단계 법칙  (0) 2025.01.17