본문 바로가기
알고리즘/이분탐색

백준 10815번 : 숫자 카드

by Jason95 2020. 12. 31.

● 문제 링크 : www.acmicpc.net/problem/10815

풀이에 참고한 링크 : 

  * C++에서 char 배열 최대 크기, int 배열 최대 크기, vector의 최대 크기 - 2heedu.tistory.com/53

  * 지역 변수의 정적 할당은 스택의 크기만큼만 할당 가능(1MB), 지역 변수의 동적 할당(힙 영역)과 전역 변수 할당은 좀 더 큰 메모리 만큼 할당 가능

    - hashcode.co.kr/questions/7996/%EB%B0%B0%EC%97%B4-%ED%81%AC%EA%B8%B0%EC%9D%98-%EC%B5%9C%EB%8C%80%EA%B0%92%EC%9D%B4-%EC%A1%B4%EC%9E%AC%ED%95%98%EB%82%98%EC%9A%94

    - bozeury.tistory.com/entry/%ED%9E%99Heap%EA%B3%BC-%EC%8A%A4%ED%83%9DStack%EC%9D%98-%EC%B5%9C%EB%8C%80-%ED%81%AC%EA%B8%B0

 * C++ 배열/벡터 정렬 - twpower.github.io/71-use-sort-and-stable_sort-in-cpp

 * C++ 동적 할당시 초기값 - boycoding.tistory.com/205


내 풀이1 (2020.12.31.) :

Visual Studio 환경에서 C++로 int 타입의 지역 변수를 정적 배열로 할당하면

배열의 크기는 약 250,000개까지 가능하다. (경우에 따라 오차는 발생)

이보다 큰 크기의 배열를 할당하려면 전역 변수로 할당하거나 동적 할당을 해야 한다.

 

이는 지역 변수의 정적 할당이 스택에서 이루어지기 때문인데,

스택의 기본 크기는 1MB이고 사전 설정을 통해 크기 조절이 가능하다.

#include <iostream>
#include <algorithm>

using namespace std;

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

	int N; cin >> N;
	int* n = new int[N]; // 동적 배열
	for (int i = 0; i < N; i++) {
		cin >> n[i];
	}
	sort(n, n + N);
	for (int i = 0; i < N; i++) {
		printf("%d ", n[i]);
	}
	cout << endl;

	int M; cin >> M;
	int* m = new int[M]; // 동적 배열
	for (int i = 0; i < M; i++) {
		cin >> m[i];
	}
	sort(m, m + M);
	for (int i = 0; i < M; i++) {
		printf("%d ", m[i]);
	}
	cout << endl;

	int index = 0;
	for (int i = 0; i < M; i++) {
		bool flag = false;
		for (int j = index; j < N; j++) {
			if (n[j] == m[i]) {
				flag = true;
				continue;
			}
		}
		if (flag==true) {
			index++;
			printf("1 ");
		}
		else {
			printf("0 ");
		}
	}

	return 0;
}

결과 : 실패

원인 : 출력 순서는 정렬하기 전의 순서여야 한다.


내 풀이2 (2020.12.31.) :

#include <iostream>

using namespace std;

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

	int* n = new int[20000001]();
	int N; cin >> N;
	for (int i = 0; i < N; i++) {
		int index; cin >> index;
		n[index+10000000] = 1;
	}
	int M; cin >> M;
	for (int i = 0; i < M; i++) {
		int index; cin >> index;
		printf("%d ", n[index+10000000]);
	}

	return 0;
}

 

결과 : 성공

분석 : 탐색에 대한 시간복잡도가 O(1)이지만 메모리를 많이 차지하는 방법


* 이분 탐색이란? wootool.tistory.com/62

* 이분 탐색 이용시, 탐색에 대한 시간복잡도가 O(n)에서 O(logn)으로 감소

* 주의 사항 : 이분 탐색은 먼저 리스트를 정렬한 상태에서 진행해야 함

* 이분 탐색 코드 예시

#include <iostream>
#include <time.h>
#include <algorithm>

using namespace std;

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	
	int size = 10; // 배열의 크기
	int value_to_find; // 찾고자 하는 값
	int index_to_find = -1; // 찾고자 하는 값의 인덱스

	int* arr = new int[size]();
	srand(time(NULL));
	for (int i = 0; i < size; i++) {
		arr[i] = rand() % 100;
	}
	sort(arr, arr + size); // 정렬된 상태에서 진행
	for (int i = 0; i < size; i++) {
		printf("%d ", arr[i]);
	}
	cout << endl;
	
	printf("찾고자 하는 값 : "); cin >> value_to_find;

	// 이진 탐색
	int left = 0, right = size - 1;
	while (left <= right) {
		int mid = (left + right) / 2;
		if (arr[mid] > value_to_find)		right = mid - 1;
		else if (arr[mid] < value_to_find)  left = mid + 1;
		else
		{
			index_to_find = mid;
			break;
		}
	}

	printf("인덱스 = %d\n", index_to_find);

	return 0;
}

* 이분 탐색(=이진 탐색 =Binary Search) 알고리즘의 라이브러리화(함수화)

1) 배열 내 이분 탐색

#include <iostream>
#include <time.h>
#include <algorithm>

using namespace std;

int my_binary_search(int* arr, int size, int value) {
	int index = -1; // 찾고자 하는 값의 인덱스
	int left = 0, right = size - 1;
	while (left <= right) {
		int mid = (left + right) / 2;
		if (arr[mid] > value)		right = mid - 1;
		else if (arr[mid] < value)  left = mid + 1;
		else
		{
			index = mid;
			break;
		}
	}
	return index;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	
	int size = 10; // 배열의 크기
	int value_to_find; // 찾고자 하는 값
	int index_to_find = -1; // 찾고자 하는 값의 인덱스

	int* arr = new int[size]();
	srand(time(NULL));
	for (int i = 0; i < size; i++) {
		arr[i] = rand() % 100;
	}
	sort(arr, arr + size); // 정렬된 상태에서 진행
	for (int i = 0; i < size; i++) {
		printf("%d ", arr[i]);
	}
	cout << endl;
	
	printf("찾고자 하는 값 : "); cin >> value_to_find;

	index_to_find = my_binary_search(arr, size, value_to_find);

	printf("인덱스 = %d\n", index_to_find);

	return 0;
}

2) 벡터 내 이분 탐색

#include <iostream>
#include <vector>
#include <time.h>
#include <algorithm>

using namespace std;

int my_binary_search(vector<int>& vec, int size, int value) {
	int index = -1; // 찾고자 하는 값의 인덱스
	int left = 0, right = size - 1;
	while (left <= right) {
		int mid = (left + right) / 2;
		if (vec.at(mid) > value)		right = mid - 1;
		else if (vec.at(mid) < value)  left = mid + 1;
		else
		{
			index = mid;
			break;
		}
	}
	return index;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	
	int size = 10; // 배열의 크기
	int value_to_find; // 찾고자 하는 값
	int index_to_find = -1; // 찾고자 하는 값의 인덱스

	vector<int> vec;
	srand(time(NULL));
	for (int i = 0; i < size; i++) {
		vec.push_back(rand() % 100);
	}
	sort(vec.begin(), vec.end()); // 정렬된 상태에서 진행
	for (int i = 0; i < size; i++) {
		printf("%d ", vec.at(i));
	}
	cout << endl;
	
	printf("찾고자 하는 값 : "); cin >> value_to_find;

	index_to_find = my_binary_search(vec, size, value_to_find);

	printf("인덱스 = %d\n", index_to_find);

	return 0;
}

3) C++ STL(algorithm 헤더 파일)에 있는 내장 함수 binary_search()

사용법 : binary_search(start_index, end_index, value_to_find); // arr와 vec 모두 가능 

리턴값 : 탐색한 value의 index를 int 타입으로 반환하지 않고, 탐색한 value의 존재 유무만 bool 타입으로 반환


내 풀이3 (2020.12.31.) - 이분 탐색 이용

 * 풀이에 참고한 링크 : jaimemin.tistory.com/991

#include <iostream>
#include <algorithm>

using namespace std;

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	
	int N, M;

	cin >> N;
	int* arr_n = new int[N]();
	for (int i = 0; i < N; i++) {
		cin >> arr_n[i];
	}
	sort(arr_n, arr_n + N);

	cin >> M;
	int* arr_m = new int[M]();
	for (int i = 0; i < M; i++) {
		cin >> arr_m[i];
	}

	for (int i = 0; i < M; i++) {
		printf("%d ", binary_search(arr_n, arr_n + N, arr_m[i]));
	}

	return 0;
}

결과 : 성공

분석 : 시간복잡도 = mlog(n)


< 코딩 테스트에서 표준 라이브러리(STL) 사용 가능 유무 >

- 이 문제의 경우, binary_search 함수 때문에 algorithm 라이브러리를 사용했음

- 삼성 역량 테스트 B형은 stdio/iostream를 제외한 모든 라이브러리 사용 불가

- 대부분의 대기업(프로그래머스 기반 코딩 테스트)은 라이브러리 사용 가능

 

'알고리즘 > 이분탐색' 카테고리의 다른 글

백준 1654번 : 랜선 자르기  (0) 2021.01.21
백준 2805번 : 나무 자르기  (0) 2021.01.17
백준 1920번 : 수 찾기  (0) 2021.01.16
이분 탐색 개념  (0) 2021.01.16