#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int arr[1002];
vector<int> two;
int main()
{
//1. Get input value
ios::sync_with_stdio(0), cin.tie(0);
int N; cin >> N;
for (int i = 0; i < N; ++i)
{
cin >> arr[i];
}
//2. Find the multiplication of all elements.
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < N; ++j)
{
two.push_back(arr[i] + arr[j]);
}
}
sort(arr, arr + N);
sort(two.begin(), two.end());
for (int i = N - 1; 0 < i; --i)
{
for (int j = 0; j < i; ++j)
{
if (binary_search(two.begin(), two.end(), arr[i] - arr[j]) == true)
{
cout << arr[i];
return 0;
}
}
}
return 0;
}
||사고 과정
처음에는 주어진 수열에서 그 수열에 속한 최대 결과값을 찾는게 막연한 느낌을 받았다.
이런 느낌을 받을 때 정의역과 공역이 확실하면 거꾸로 하는게 대부분이여서 이번에도 거꾸로 해보기로 했다.
그래서 주어진 수열을 오름차순으로 정렬하여 마지막 원소부터 세 원소의 합이 가능한지 살펴보았는데
O(n^3)보다 작은 방법을 찾지 못했다..ㅠ
한시간쯤 시도 후 찾지 못해 다른 사람의 풀이를 보고 다시 혼자 풀어 보았다.
방법은 두 원소의 모든 합을 저장하여 이분탐색으로 찾아가며 풀이하는 방법이였다..
어떻게 보면 무식한 방법인데 시간을 계산해보면 O(N^2 * logN)의 복잡도로 괜찮은 방법이였다.
||사용 기법
- Binary search
||풀면서 느낀 것
- 시간 복잡도 계산을 해보자
시간 복잡도를 대강 보지 말고 내 방법에 대한 복잡도 계산을 해보는 걸 지금부터라도 해야겠다.
- 이러한 유형 기억
이분 탐색에서 이렇게 어떤 수끼리 묶고 탐색을 하는 경우가 많다고 한다. 잘 기억해둘것!
||더 나은 풀이
바뀐 부분만 적으면
//2. Find the multiplication of all elements.
for (int i = 0; i < N; ++i)
{
for (int j = i; j < N; ++j)
{
two.push_back(arr[i] + arr[j]);
}
}
sort(arr, arr + N);
sort(two.begin(), two.end());
for (int i = N - 1; 0 < i; --i)
{
for (int j = i - 1; 0 <= j; --j)
{
if (binary_search(two.begin(), two.end(), arr[i] - arr[j]) == true)
{
cout << arr[i];
return 0;
}
}
}
첫번째의 이중 반복문에서 중복 되는 경우를 없애 주었다.
두번째의 이중 반복문에서 i와 같은 값의 j를 빼는 경우를 제외했다.
이러한 처리 후 시간이 반 정도 절약 됐다.