*발 안녕
너희는 백준 2477번 참외밭 문제를 풀어보았니?
문제에서 젖비린내 난다고?
*발 샤워부터 하고 와 파오후 *들아ㅋㅋ
거두절미(去頭截尾)하고 시간 초과가 났던 이 문제를 다시 생각해 보면서
시간 복잡도와 수행 시간에 대해 알아보자고
cpu가 1초안에 수행할 수 있는 연산은 1억번이라고 생각하는것이 국룰이란다
그러면 상당히 간단해 지는데,
시간제한이 1초라면 (N은 입력) 대략
O(1), O(log N) | N <= ∞ |
O(N) | N <= 100,000,000(1억) |
O(N log N) | N <= 13,993,959(1천 3백만) |
O(N²) | N <= 10,000(1만) |
O(N³) | N <= 464 |
O(2ᴺ) | N <= 26 |
O(N!) | N <= 12 |
이정도로 어림잡을 수 있다.
물론 빅 오 노테이션(Big-O notation)을 기준으로 했기때문에
무시되는 상수나 마이너 항들을 고려한다면 결과가 또 천차 만별이 될것이니 참고 하도록 해
*나게 유용하군
자, 이제 문제로 돌아가 보자고
이 문제에서 입력받을 수 있는 최대 자료 개수는
1,000,000개 라는 것을 알 수 있지
처음 순수했던 나는 이분탐색은 커녕 정렬도 안하고 선형탐색으로 풀려고 했지 (저능아는 아니고 3달만에 풀어서 그럼)
이 코드는 너무 역해서 보여주진 못하고 대충 계산만 해본다면
O(N²) 이니까 250,000,000,000 번의 연산 = 25초가 걸린다
오랫만에 시간초과를 보니까 아찔하더라
그래서 정신 차리고 수정을 해봤어.
정렬을 하고 이진탐색을 하는 방식으로 말이지
하지만 멍청하게도 나는 정렬을 선택정렬로 해버렸고 똑같이 250,000,000,000의 연산을 하게 된 백준의 컴퓨터는
이렇게 큰 연산은 안들어 간다며 처참히 부서지고 말았지
두번의 같은 실수를 저지르고 나는 나에게 큰 실망을 해버렸지
그래서 그 다음은 바로 합병정령 빡구현을 박아버렸지
이게 마지막 코드야
#include <stdio.h>
int binary_search(int *arr, int start, int end, int target)
{
if (start < end)
{
int middle = start + (end - start) / 2;
if (arr[middle] == target)
return 1;
else if (target < arr[middle])
return binary_search(arr, start, middle, target);
else
return binary_search(arr, middle + 1, end, target);
}
else if (arr[start] == target)
return 1;
return 0;
}
int* merge(int* arr, int start, int middle, int end){
int i = start, j = middle+1, k = 0;
int sorted[end-start+1];
while(i <= middle && j <= end)
{
if(arr[i] <= arr[j])
{
sorted[k] = arr[i];
i++;
}
else{
sorted[k] = arr[j];
j++;
}
k++;
}
if(i > middle)
{
while(j <= end)
{
sorted[k] = arr[j];
k++;j++;
}
}
else{
while(i <= middle)
{
sorted[k] = arr[i];
k++;i++;
}
}
for(int l=start; l<=end; l++)
{
arr[l] = sorted[l-start];
}
return arr;
}
int* merge_sort(int* arr, int start, int end)
{
if(start < end)
{
int middle = (start + end) / 2;
merge_sort(arr, start, middle);
merge_sort(arr, middle+1, end);
merge(arr, start, middle, end);
}
return arr;
}
int main()
{
int n, m;
scanf("%d", &n);
int a[n];
for(int i=0; i < n; i++)
{
scanf("%d", &a[i]);
}
merge_sort(a, 0, n);
scanf("%d", &m);
int b[m];
for(int i=0; i < m; i++)
{
scanf("%d", &b[i]);
printf("%d ", binary_search(a, 0, n, b[i]));
}
}
사용된 알고리즘인 합병정렬과 이분탐색은 각각
합병정렬 | O(N log N) | 6000000 |
이분탐색 | O(log N) | 6 |
(대략)번의 연산을 한다.
그렇기 때문에 빅 오 표기법 기준으로 6000006번의 연산이 이루어 지고 이는 이론적으로 0.6초의 수행시간을 가져간다
어때 이해가 잘 됐니??
이제 시간 초과가 뜨면 노트북 덮고 롤하러 가지 말고
시간복잡도를 생각하면서 다시 설계를 해보도록 하렴
이제 부모님께 효도 해야지
사랑해요:)
'알고리즘 시*련아' 카테고리의 다른 글
C++ 백준 1008번에 관해 (0) | 2022.10.27 |
---|---|
C++ STL sort() - 정렬6 (0) | 2022.08.06 |
C++ 병합 정렬(합병 정렬) - 정렬5 (0) | 2022.08.05 |
C++ 퀵정렬 - 정렬4 (0) | 2022.08.05 |
C++ 삽입 정렬 - 정렬3 (0) | 2022.08.04 |