- Today
- Total
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- map
- deep dive
- 알고리즘
- async
- 백준
- React
- 프론트엔드
- 네트워크
- get
- Angular
- 에러처리
- js
- 모던 자바스크립트
- JavaScript
- http
- 웹
- error
- 상태관리
- 그림으로 배우는 http&network
- es6
- 비동기
- C++
- Java Script
- 모던 자바스크립트 deep dive
- git
- html
- git error
- 자바스크립트
- 백준 실버
- 이터러블
sharingStorage
백준 10816 - 숫자카드 2 본문
문제요약
상근이가 가지고 있는 숫자카드 N, 숫자를 M개 입력받은 후 입력받은 숫자와 같은 카드를 상근이가 몇개 가지고 있는지 구하는 문제
접근
- 입력을 받을 때 마다 0으로 초기화한 배열에 입력받은 수의 배열값에 +1을 한다.
- 음수도 입력받아야 하므로 인덱스는 입력받은 수 + 0으로 만들 수 있는 최대수 (10,000,000)으로 설정한다.
- 그리고 M개의 숫자를 입력받고 그에 해당하는 배열 값을 출력한다.
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<map>
using namespace std;
vector<int> v;
int N, M;
int sum;
int convertNum[20000001] = { 0 };
int negativeToPositive = 10000000;
int main() {
//ios_base::sync_with_stdio(false);
//cin.tie(NULL);
cin >> N;
int temp;
for (int i = 0; i < N; i++) {
cin >> temp;
convertNum[temp + negativeToPositive]++;
}
cin >> M;
for (int i = 0; i < M; i++) {
cin >> temp;
cout << convertNum[temp + negativeToPositive]<<" ";
}
return 0;
}
실패의 원인
//ios_base::sync_with_stdio(false);
//cin.tie(NULL);
위 주석을 풀어주어야 합니다.
ios_base::sync_with_stdio(false)
ios_base::sync_with_stdio(false) 는 c의 stdio와 iostream을 동기화 시켜주는 역할을 하는데 이 떄 iostream과 stdio의 버퍼를 모두 사용하기 때문에 딜레이가 발생하여 시간초과가 났습니다.
이 코드를 작성해주어 동기화를 비활성화 시켜줍니다.
c++만의 독립적인 버퍼를 생성시켜 c의 버퍼와 병행하여 사용할 수 없게 하여, 버퍼의 수를 줄이고 실행 속도는 빨라지게 됩니다.
※ 주의
위 코드를 넣었을 때 멀티 쓰레드 환경에서 출력 순서를 보장할 수 없습니다.
또, 버퍼가 분리되었기 때문에 cin과 C의 scanf, gets, getchar등을 같이 사용하면 안되고
cout과 C의 printf, puts, putchar등을 같이 사용하면 예상치 못한 결과를 얻을 수 있습니다.
cin.tie(NULL)
이 코드는 cin과 cout의 묶음을 풀어줍니다.
기본적으로 cin과 cout은 묶여있고 한 스트림이 다른 스트림에서 각 IO작업을 진행하기 저에 자동으로 버퍼를 비워줌을 보장합니다.
이를 사용하면 cin과 cout에 순서를 확실히 보장받을 수 없을 가능성도 있지만 입력을 많이 받아야하는 실패1 과 같은 코드에서는 사용하는 것을 추천합니다.
접근2
N과 M을 입력받고 그대로 탐색하면 log N^2이 되므로 시간초과가 날 것 입니다. 따라서 이분탐색으로 접근해보려고 합니다.
- 이분탐색을 위해 N개의 수를 정렬한다.
- 이분탐색을 진행하는데, 카드의 개수를 세야하므로 해당 수가 등장하는 마지막 인덱스 - 첫 인덱스 +1을 해준다.
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int N, M;
int lower_bound(int start, int end, int value) {
int mid = 999;
while (start <= end) {
mid = (start + end) / 2;
if (v[mid]>=value) {
end = mid-1;
}
else {
start = mid + 1;
}
}
return start; //해당 숫자카드의 첫 번째 인덱스
}
int upper_bound(int start, int end, int value) {
int mid = 999;
while (start <= end) {
mid = (start + end) / 2;
if (v[mid] <= value) {
start = mid + 1;
}
else {
end = mid-1;
}
}
return end; //해당 숫자카드의 마지막 인덱스
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cin >> N;
int temp;
for (int i = 0; i < N; i++) {
cin >> temp;
v.push_back(temp);
}
sort(v.begin(), v.end());
cin >> M;
int num, start , end,low,up;
for (int i = 0; i < M; i++) {
cin >> num;
start = 0;
end = N-1;
low= lower_bound(start, end, num);
up = upper_bound(start, end, num);
cout << up - low +1 << " ";
}
return 0;
}
고찰
이분탐색은 시간은 느리지만 메모리는 현저히 적게 사용하였고, 배열을 이용한 값 체크는 20000001이라는 배열크기 때문에 메모리를 상당히 잡아먹었지만 조금 더 빨랐다.
이러한 트레이드 오프를 생각하면서 알고리즘에 접근한다면 더 효율적인 로직에 접근할 수 있을 것 같다.
sync_with_stdio를 복붙해두면서 써서 의미를 제대로 알지 못하고 쓰다가 이번 기회에 확실히 알게된 것 같다. 많은 입력을 받을 땐 입출력에서 시간을 줄이는 방안을 생각해보기도 해야겠다.
'알고리즘' 카테고리의 다른 글
백준 18311 - 왕복 (0) | 2023.04.10 |
---|---|
C++ STL priority_queue 우선순위큐 (0) | 2023.01.10 |
백준 1541 - 잃어버린 괄호 (0) | 2023.01.02 |
백준 1758 - 알바생강호(c++, Greedy) (3) | 2022.12.03 |