-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1320ee9
commit eec0007
Showing
2 changed files
with
123 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
#include<iostream> | ||
#include<algorithm> | ||
#include<unordered_map> | ||
|
||
using namespace std; | ||
|
||
int main(int argc, char** argv) | ||
{ | ||
ios_base::sync_with_stdio(false); | ||
cin.tie(nullptr); | ||
cout.tie(nullptr); | ||
|
||
int n, q; | ||
cin >> n >> q; | ||
|
||
int cars[50000]; | ||
for (int i = 0; i < n; ++i) | ||
cin >> cars[i]; | ||
|
||
sort(cars, cars + n); | ||
|
||
unordered_map<int, int> map; | ||
for (int i = 0; i < n; ++i) | ||
map[cars[i]] = i + 1; | ||
|
||
for (int i = 0; i < q; ++i) { | ||
int m, m_idx; | ||
cin >> m; | ||
m_idx = map[m]; | ||
cout << (m_idx ? (m_idx - 1) * (n - m_idx) : m_idx) << '\n'; | ||
} | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# [7차 Softeer 정기 역량 진단] 1번 - 자동차 테스트 | ||
|
||
## 카테고리 | ||
|
||
자료구조, 해시 테이블 | ||
|
||
## 시간복잡도 | ||
|
||
`O(N * log N + Q)` | ||
|
||
## 문제 | ||
|
||
자동차의 연비들을 제공해준다. | ||
|
||
자동차 중 임의의 3개를 골랐을 때, 중앙값이 `m`이 될 수 있는 서로 다른 경우의 수를 구하라. | ||
|
||
n대의 자동차에 대한 연비의 정보와 `q`개의 `m`값이 주어진다. | ||
|
||
## 제약 조건 | ||
|
||
- 1 ≤ n ≤ 50,000 | ||
- 1 ≤ q ≤ 200,000 | ||
- 1 ≤ 연비 ≤ 1,000,000,000 | ||
- 1 ≤ m ≤ 1,000,000,000 | ||
- 각 차량의 연비는 모두 다르다. | ||
|
||
## 시간 제약 | ||
|
||
- Java : 3초 | ||
- C++ : 2초 | ||
- Python : 2초 | ||
|
||
# 입력 형식 | ||
|
||
- 첫 번째 줄에 `n`, `q`가 주어진다. | ||
- 두 번째 줄에 `n`개의 자동차의 연비에 해당하는 값이 공백을 사이에 두고 주어진다. | ||
- 세 번째 줄부터 `q`개의 줄에 걸쳐 각 줄에 `m`값이 주어진다. | ||
|
||
# 출력 형식 | ||
|
||
`q`개의 줄에 걸쳐 각 줄에 `m`값이 중앙값이 될 수 있는 서로 다른 경우의 수를 출력한다. | ||
|
||
## 해설 | ||
|
||
데이터를 입력받는다. `O(N)` | ||
|
||
```cpp | ||
int n, q; | ||
cin >> n >> q; | ||
|
||
int cars[50000]; | ||
for (int i = 0; i < n; ++i) | ||
cin >> cars[i]; | ||
``` | ||
|
||
입력받은 데이터를 정렬한다. `O(N * log N)` | ||
|
||
```cpp | ||
sort(cars, cars + n); | ||
``` | ||
정렬된 데이터를 키로, 인덱스를 값으로 하는 해시 테이블을 만든다. 이때 해시 테이블에 없는 값을 조회했을때 나오는 리턴값인 `0`과 구분을 위해 인덱스에 `1`을 더해서 저장한다. `O(N)` | ||
```cpp | ||
unordered_map<int, int> map; | ||
for (int i = 0; i < n; ++i) | ||
map[cars[i]] = i + 1; | ||
``` | ||
|
||
`q`개의 `m`값을 입력받아 해시 테이블에서 조회한다. 3개의 값을 뽑았을 때, `m`이 중간값이 되는 경우는 `m`의 왼쪽에서 한 개, `m`의 오른쪽에서 한 개를 뽑는 경우의 수와 같다. 이는 `m`의 왼쪽 개수 * `m`의 오른쪽 개수로 상수시간으로 계산이 가능하다. `O(q)` | ||
|
||
```cpp | ||
for (int i = 0; i < q; ++i) { | ||
int m, m_idx; | ||
cin >> m; | ||
m_idx = map[m]; | ||
cout << (m_idx ? (m_idx - 1) * (n - m_idx) : m_idx) << '\n'; | ||
} | ||
``` | ||
|
||
## 문제 분석 | ||
|
||
문제의 제약조건에서 알 수 있다싶이, `n`의 최대값이 `50,000`이고 `q`의 최대값이 `200,000`이다. `n`이 `50,000`이고 `q`가 `200,000`이라면, `n`개의 자동차 중 임의의 3개를 직접 골라서, 중앙값이 `m`이 될 수 있는 서로 다른 경우의 수를 구하는 것은 `O(N^3)`의 시간복잡도를 가진다. 이는 제한시간인 `2초`를 넘어가기 때문에, `O(N^3)`의 알고리즘으로는 풀 수 없다. | ||
|
||
이는 최소한 `O(Q * log N)`의 알고리즘으로 풀어야 한다는 것을 의미한다. | ||
|
||
`O(Q * log N)`의 알고리즘으로 풀기 위해서는, `n`개의 자동차의 연비를 정렬한 다음 각 `q`에 대해 `m`의 인덱스를 이진 탐색으로 찾아야 한다. | ||
|
||
본 풀이와 같이 해시 테이블을 이용한 `O(N * log N + Q)` 알고리즘으로도 풀 수 있다. |