-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Vinjunho/feature/boj 2075 N번째큰수 #298
Open
Rekalux
wants to merge
4
commits into
molgorithm:main
Choose a base branch
from
Rekalux:vinjunho/feature/boj-2075
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,41 @@ | ||
# 백준 2075 N번째 큰 수 | ||
|
||
[문제 링크](https://www.acmicpc.net/problem/7662) | ||
|
||
## 1. 설계 로직 | ||
|
||
1. n^2개의 수 중에서 n번째의 수를 구하는 문제이다. | ||
2. n^2개의 데이터를 모두 관리할 필요가 없다 | ||
3. 상위 n개만 관리하여 n번째 수를 뽑아내면 되겠다. | ||
4. 이분탐색을 통해 랭킹을 관리하면 더 효율적. | ||
|
||
|
||
|
||
- (n^2)log(n) , 1<=n<=1500 | ||
|
||
## 2. 코드 | ||
|
||
```python | ||
import sys, bisect | ||
|
||
input = sys.stdin.readline | ||
n = int(input()) | ||
lank = [] # 상위 n개의 수만 관리할 list | ||
for _ in range(n): | ||
li = list(map(int, input().split())) # readline | ||
for i in range(n): | ||
bisect.insort(lank, -li[i]) # 크기순으로 정렬하며 삽입한다(bisect는 이분탐색활용하므로 O(log(n)) | ||
if len(lank) > n: # 상위 n번째 이 후의 수는 볼 이유 없으므로 삭제 | ||
lank.pop() # 리스트 맨 끝을 날리는 pop()함수는 O(1) | ||
print(-lank[-1]) # n번째 수를 출력 | ||
|
||
``` | ||
|
||
|
||
|
||
## 3. 후기 | ||
|
||
- 어제 우선순위큐와 이분탐색에 대해 공부하다 bisect라는 말도 안 되는 라이브러리를 알게되었다. | ||
- 앞으로 이분탐색이 필요할 때 많이 써먹어야겠다. | ||
- 파이썬 사기 | ||
|
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,12 @@ | ||
import sys, bisect | ||
|
||
input = sys.stdin.readline | ||
n = int(input()) | ||
lank = [] # 상위 n개의 수만 관리할 list | ||
for _ in range(n): | ||
li = list(map(int, input().split())) # readline | ||
for i in range(n): | ||
bisect.insort(lank, -li[i]) # 크기순으로 정렬하며 삽입한다(bisect는 이분탐색활용하므로 O(log(n)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. bisect 미쳤네요 |
||
if len(lank) > n: # 상위 n번째 이 후의 수는 볼 이유 없으므로 삭제 | ||
lank.pop() # 리스트 맨 끝을 날리는 pop()함수는 O(1) | ||
print(-lank[-1]) # n번째 수를 출력 |
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,144 @@ | ||
# 백준 7662 이중 우선순위 큐 | ||
|
||
[문제 링크](https://www.acmicpc.net/problem/7662) | ||
|
||
## 1. 설계 로직 | ||
|
||
- ### java | ||
|
||
1. 입력과 출력에 log(n) 을 원함 | ||
2. 정렬된 자료구조가 필요함 | ||
3. 중복을 제거해 줄 자료구조가 필요함 | ||
4. Treemap으로 한 번에 해결 | ||
5. I면 Treemap에 넣고 이미 존재하면 개수만 늘린다 | ||
6. D 1 이면 lastkey를 활용해 맨 오른쪽 노드 제거, D -1이면 firstkey를 활용해 맨 왼쪽 노드 제거(개수가 남아 있다면 개수만 1 줄임) | ||
7. 비어있다면 Entry, 존재하면 lastkey, firstkey를 각각 출력한다 | ||
|
||
- n log(n) | ||
|
||
|
||
|
||
- ### python | ||
|
||
1. 입력과 출력에 log(n) 을 원함 | ||
2. 정렬된 자료구조가 필요함 | ||
3. 중복을 제거해 줄 자료구조가 필요함 | ||
4. 작은 수를 기준으로 하는 우선순위 큐, 큰 수를 기준으로 하는 우선순위 큐 이렇게 2개 만든다 | ||
5. I이면 두 큐에 모두 저장한다. 단, 인덱스 값을 넣어서 서로가 같은 수임을 인식시킨다 | ||
6. D 1 이면 내림차순 큐에서 제거, D -1이면 오름차순 큐에서 제거 | ||
7. 하나의 명령이 끝날 때마다 동시에 pop 값이 없는지 양쪽 큐를 확인한다. 있다면 최대한 pop한다. | ||
8. 비어있다면 Entry, 존재하면 각 큐를 pop하여 출력한다 | ||
|
||
- n log(n) | ||
|
||
## 2. 코드 | ||
|
||
- ### java | ||
|
||
```python | ||
import java.io.BufferedReader; | ||
import java.io.IOException; | ||
import java.io.InputStreamReader; | ||
import java.util.StringTokenizer; | ||
import java.util.TreeMap; | ||
|
||
public class Main { | ||
public static void main(String[] args) throws IOException { | ||
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); | ||
int T = Integer.parseInt(br.readLine()); | ||
for (int tc = 0; tc < T; tc++) { | ||
int n = Integer.parseInt(br.readLine()); | ||
TreeMap<Integer, Integer> map = new TreeMap<Integer, Integer>(); | ||
for (int i = 0; i < n; i++) { | ||
StringTokenizer st = new StringTokenizer(br.readLine()); | ||
String command = st.nextToken(); | ||
int num = Integer.parseInt(st.nextToken()); | ||
if (command.equals("I")) { | ||
if (map.containsKey(num)) { | ||
map.put(num, map.get(num) + 1); | ||
} else { | ||
map.put(num, 1); | ||
} | ||
} else { | ||
if (map.size() > 0) { | ||
int del_key = 0; | ||
if (num == 1) { | ||
del_key = map.lastKey(); | ||
} else { | ||
del_key = map.firstKey(); | ||
} | ||
int del_num = map.get(del_key) - 1; | ||
if (del_num == 0) { | ||
map.remove(del_key); | ||
} else { | ||
map.put(del_key, del_num); | ||
} | ||
} | ||
} | ||
} | ||
if (map.size() == 0) { | ||
System.out.println("EMPTY"); | ||
} else { | ||
System.out.println(map.lastKey() + " " + map.firstKey()); | ||
} | ||
} | ||
|
||
} | ||
} | ||
``` | ||
|
||
- ### python | ||
|
||
``` | ||
import sys | ||
import heapq | ||
|
||
input = sys.stdin.readline | ||
T = int(input()) | ||
for _ in range(T): | ||
n = int(input()) | ||
nq, mq = [], [] | ||
visit = [False] * (n + 1) # 지워진 번호 (입력된 순서) | ||
for i in range(n): | ||
command, num = input().split() | ||
num = int(num) | ||
if command == 'I': # 입력 명령이면 | ||
heapq.heappush(nq, (num, i)) # 작은수우선 | ||
heapq.heappush(mq, (-num, i)) # 큰수우선 | ||
continue | ||
elif num == 1 and mq: # 지우라는 명령어에 지울 값이 있으면 | ||
visit[heapq.heappop(mq)[1]] = True # 입력된 값을 지우고 지웠음을 저장한다 | ||
elif num == -1 and nq: # 지우라는 명령어에 지울 값이 없으면 | ||
visit[heapq.heappop(nq)[1]] = True # 입력된 값을 지우고 지웠음을 저장한다 | ||
while nq and visit[nq[0][1]]: # nq에서 제거할 수 있을만큼 제거하겠다. | ||
heapq.heappop(nq) | ||
while mq and visit[mq[0][1]]: # mq에서 제거할 수 있을만큼 제거하겠다. | ||
heapq.heappop(mq) | ||
print(f'{-mq[0][0]} {nq[0][0]}' if nq else 'EMPTY') | ||
|
||
``` | ||
|
||
## 3. 후기 | ||
|
||
- ### java | ||
|
||
- 이 문제는 AVL Tree 혹은 Red-Black Tree를 활용하라는 문제로 보인다. | ||
|
||
- 그러나 이 문제에서 자료구조 그 자체를 구현하기에는 무리가 있으므로 있는 자료구조를 활용해서 최대한 문제에 접근하는 것이 중요하겠다. | ||
|
||
- Java에는 Treemap이라는 파워풀한 자료구조(RB Tree 기반)가 존재해서 쉽게 풀 수 있었다. | ||
|
||
- Treemap은 Map의 Key, Value값을 가지면서 이분탐색트리의 구조를 띄고 있어 정렬된 구조를 갖는다. | ||
|
||
- 입력,출력에 log(n) 밖에 걸리지않고, 내부적으로 균형을 맞추기위해 회전도 알아서 해준다. | ||
|
||
- 자바 사기 | ||
|
||
- ### python | ||
|
||
- Python에는 정렬이 되며 이분탐색하는 자료구조는 존재하지 않는다. 있다고 하더라도 삭제에 log(n) 이 소모되는 자료구조는 기본적으로 제공하지 않는듯하다. | ||
- 우리가 알아야 할 값은 최소값, 최대값으로 기준이 2개이므로 각각의 기준에 맞는 우선순위큐를 활용한다. | ||
- 서로의 큐가 같은 데이터를 공유하고 있어야 한다는 점에서 인덱스를 활용하는 방법과 dictionary를 활용하는 2가지의 방법이 있겠다 | ||
- 삽입에 이분탐색을 적용하고 삭제에 O(n)을 소비시켜도 통과하는 것도 확인했다. 저격케이스 뜨면 바로 시간초과다. 그러나 의도가 중복을 제거하라는 부분이라 삭제 시간 초과는 큰 문제가 아닌 것 같다. 심지어는 속도도 더 빠른 결과가 나와 오히려 당황스럽다. 하하 | ||
- 자바 사기 | ||
|
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,49 @@ | ||
import java.io.BufferedReader; | ||
import java.io.IOException; | ||
import java.io.InputStreamReader; | ||
import java.util.StringTokenizer; | ||
import java.util.TreeMap; | ||
|
||
public class boj7662 { | ||
public static void main(String[] args) throws IOException { | ||
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); | ||
int T = Integer.parseInt(br.readLine()); | ||
for (int tc = 0; tc < T; tc++) { | ||
int n = Integer.parseInt(br.readLine()); | ||
TreeMap<Integer, Integer> map = new TreeMap<Integer, Integer>(); | ||
// TreeMap은 정렬과 동시에 Map의 역할을 수행 key는 입력받은 숫자, value는 개수 | ||
for (int i = 0; i < n; i++) { | ||
StringTokenizer st = new StringTokenizer(br.readLine()); | ||
String command = st.nextToken(); | ||
int num = Integer.parseInt(st.nextToken()); | ||
if (command.equals("I")) { | ||
if (map.containsKey(num)) { // 이미 존재하는 값이면 | ||
map.put(num, map.get(num) + 1); // 개수만 증가 | ||
} else { | ||
map.put(num, 1); // 없으면 추가 | ||
} | ||
} else { | ||
if (map.size() > 0) { | ||
int del_key = 0; // 지울 key 초기화 | ||
if (num == 1) { | ||
del_key = map.lastKey(); // 가장 뒤에 있는 = 가장 키값이 큰 | ||
} else { | ||
del_key = map.firstKey(); // 가장 앞에 있는 = 가장 키값이 작은 | ||
} | ||
int del_num = map.get(del_key) - 1; // 개수를 줄여보고 | ||
if (del_num == 0) { // 0이면 삭제 | ||
map.remove(del_key); | ||
} else { | ||
map.put(del_key, del_num); // 그 외엔 업데이트 | ||
} | ||
} | ||
} | ||
} | ||
if (map.size() == 0) { | ||
System.out.println("EMPTY"); | ||
} else { | ||
System.out.println(map.lastKey() + " " + map.firstKey()); | ||
} | ||
} | ||
} | ||
} |
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,25 @@ | ||
import sys | ||
import heapq | ||
|
||
input = sys.stdin.readline | ||
T = int(input()) | ||
for _ in range(T): | ||
n = int(input()) | ||
nq, mq = [], [] | ||
visit = [False] * (n + 1) # 지워진 번호 (입력된 순서) | ||
for i in range(n): | ||
command, num = input().split() | ||
num = int(num) | ||
if command == 'I': # 입력 명령이면 | ||
heapq.heappush(nq, (num, i)) # 작은수우선 | ||
heapq.heappush(mq, (-num, i)) # 큰수우선 | ||
continue | ||
elif num == 1 and mq: # 지우라는 명령어에 지울 값이 있으면 | ||
visit[heapq.heappop(mq)[1]] = True # 입력된 값을 지우고 지웠음을 저장한다 | ||
elif num == -1 and nq: # 지우라는 명령어에 지울 값이 없으면 | ||
visit[heapq.heappop(nq)[1]] = True # 입력된 값을 지우고 지웠음을 저장한다 | ||
while nq and visit[nq[0][1]]: # nq에서 제거할 수 있을만큼 제거하겠다. | ||
heapq.heappop(nq) | ||
while mq and visit[mq[0][1]]: # mq에서 제거할 수 있을만큼 제거하겠다. | ||
heapq.heappop(mq) | ||
print(f'{-mq[0][0]} {nq[0][0]}' if nq else 'EMPTY') |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
문제 링크가 잘못되었습니다!!!!! 수정 부탁드립니다