2022. 6. 15. 00:46ㆍTIL💡/Algorithms
https://www.acmicpc.net/problem/7453
7453번: 합이 0인 네 정수
첫째 줄에 배열의 크기 n (1 ≤ n ≤ 4000)이 주어진다. 다음 n개 줄에는 A, B, C, D에 포함되는 정수가 공백으로 구분되어져서 주어진다. 배열에 들어있는 정수의 절댓값은 최대 228이다.
www.acmicpc.net
처음에 풀 때는 정신없이 풀었는데 왜 굳이 이렇게 풀었는지 한 번 정리해볼 필요가 있어보였다.
효율성을 생각하지 않는다면 A,B,C,D 배열 요소마다 조합을 만들어서 배열의 합이 0인지를 확인한다. 이렇게 된다면 $O(N^4)$이라는 시간복잡도를 가지게 된다. (비효율 그자체..)
이런 상황을 방지하기 위해 A,B 배열을 합치고 C,D 배열을 합쳐서 4개의 배열을 2개의 배열로 만든다. 이로써 각각 $O(N^2)$라는 시간복잡도를 가지도록 한다. 그리고 A와 B를 합친 값과 C와 D를 합친 값의 합이 0이 되도록 하는 조합을 찾아야 한다. 그리고 후에 정렬로 $O(nlogn)$, 이분탐색 기반의 lower_bound, upper_bound을 사용하면서 이 부분에서는$O(logn)$이라는 시간 복잡도가 소요된다.
따라서 최종적으로 $O(n^2logn)$의 복잡도를 가지므로 4개의 배열을 모두 조합해보는 경우보다는 효율적이다.
💡깨알팁
미리 메모리 공간을 확보(할당)하고 인덱스로 값을 넣어주는 게 매번 push_back
하는 것보다 빠르다.
equal_range
는 lower_bound, upper_bound를 동시에 리턴한다.
왜 map을 쓰면 시간이 초과할까?
많은 사람들이 질문에 map을 사용한 후 시간이 초과한다는 질문을 남겨서 이에 대한 고민도 해소해보려고 한다.
사람들은 아무래도 A와 B를 합친 값과 C와 D를 합친 값을 key로, 등장하는 횟수는 value로 각각 map으로 만들어서 조합을 간편하게 만들려고 했던 것 같다. 하지만 이는 실패로 돌아가고 마는데,,,
왜냐하면 해시 충돌(Hash Collison)
로 인해 map의 효율적인 알고리즘이 수포로 돌아가고 만다.
해시충돌로 인해 랜덤 접근이 불가능해지고 최악의 경우 $O(N)$의 시간 복잡도를 가지게 된다. 따라서 이분 탐색 기반의 lower_bound, upper_bound보다 비효율적인 탐색이 될 가능성이 생긴다.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> a(n), b(n), c(n), d(n);
for(int i = 0;i < n;i++) {
cin >> a[i] >> b[i] >> c[i] >> d[i];
}
vector<int> first, second;
for(int i = 0;i < n;i++) {
for(int j = 0;j < n;j++){
first.push_back(a[i] + b[j]);
second.push_back(c[i] + d[j]);
}
}
sort(second.begin(), second.end());
long long ans = 0;
for(int num : first) {
auto range = equal_range(second.begin(), second.end(), -num);
ans += range.second - range.first;
}
cout << ans << endl;
return 0;
}
'TIL💡 > Algorithms' 카테고리의 다른 글
[Codeforces] 1694B. Paranoid String (0) | 2022.06.17 |
---|---|
[Codeforces] 1694A. Creep (0) | 2022.06.17 |
[LeetCode] 981. Time Based Key-Value Store with lower_bound (0) | 2022.06.14 |
[Codeforces] 481. Magical String (0) | 2022.06.14 |
[Codeforces] awoo's Favorite Problem with Two Pointers💥 (0) | 2022.06.14 |