포스트

10816 숫자 카드 2

1920 수 찾기 문제의 업그레이드 버전

수 찾기 문제가 기초적인 이분 탐색 문제라면

10816 숫자 카드 2 문제는

이분 탐색을 통해 원소의 개수를 구해야한다

1. 문제


간단 설명

총 카드 N개를 가지고 있을 때,

M번에 걸쳐 카드 번호가 주어지고 이 카드가 몇개 있는지 확인하는 문제

2. 문제 분석


이분 탐색을 이용하거나, 해시맵을 이용하는 방법이 있다

해시 맵을 사용하는 방법은 너무 쉬우므로 이분 탐색을 이용함

필요변수

전체 숫자 카드 개수 int N (N <= 500,000)

각 카드의 숫자는 -10,000,000 <= card <=10,000,000 이므로 int형으로 처리 가능

N개의 숫자 카드를 담을 배열 vector<int> arr

M개의 테스트 케이스 int M

몇개나 가지고 있는지 체크할 카드의 숫자 int card

주의점

  • 입출력양이 많으므로 시간 초과에 주의
  • 이분 탐색을 직접 구현 시, 배열을 call by value 형식으로 줘버리면 오버헤드 발생

알고리즘

1
2
3
4
5
6
1. N을 입력받는다
2. N개의 카드들을 벡터에 넣는다
3. arr 벡터를 정렬한다
4. M을 입력는다
5. M회에 걸쳐 카드의 정보를 입력받는다
6. upper_bound(card) - lower_bound(card) 를 하면, 해당 원소가 몇개있는지 확인할 수 있다

6번의 upper_bound(card) - lower_bound(card) 부분에 대헤 자세히 설명하자면

upper_bound(card)는 card 숫자 보다 더 큰 원소가 나오는 지점의 인덱스을 리턴한다

lower_bound(card)는 card 숫자와 같거나 더 큰 원소가 처음으로 나오는 지점의 인덱스를 리턴한다

예를들어 카드가 {1,2,3,4,4,4,5,6} 이 있다면

upper_bound(4)는 4보다 큰 5가 나오는 지점인 index = 6를 리턴하고

lower_bound(4)는 4가 처음 나오는 지점인 index = 3을 리턴한다

두 인덱스를 빼주면 해당 원소가 몇개 있는지 알 수 있다

더 자세한 설명은 Lower Bound, Upper Bound 참고

3. 소스코드


C++ STL의 lower upper bound 이용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

int N, M;
int card;
vector<int> arr;

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);

	freopen_s(new FILE*, "input.txt", "r", stdin);
	cin >> N;
	arr.resize(N);
	for (int i = 0; i < N; i++) {
		cin >> card;
		arr[i] = card;
	}

	sort(arr.begin(), arr.end());

	cin >> M;
	while (M--) {
		cin >> card;
		cout << upper_bound(arr.begin(), arr.end(), card) - lower_bound(arr.begin(), arr.end(), card) << " ";
	}

	return 0;
}

unordered map 이용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <unordered_map>
#include <algorithm>

using namespace std;

int N, M;
int card;

int main() {
    ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	// freopen_s(new FILE*, "input.txt", "r", stdin);
	cin >> N;
	
	unordered_map<int, int> um;

	for (int i = 0; i < N; i++) {
		cin >> card;
		um[card]++; // 이렇게 간단히 추가할 수 잇음
	}

	cin >> M;
	while (M--) {
		cin >> card;
		cout << um[card] << " ";
	}

	return 0;
}
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.