Skip to content
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

[맵과 셋] 3월 8일 #2

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

[맵과 셋] 3월 8일 #2

wants to merge 2 commits into from

Conversation

sbeencho
Copy link
Collaborator

@sbeencho sbeencho commented Mar 14, 2022

내용 & 질문

2776번 해결이 잘되지 않아서 추가제출 합니다!

<기존 제출>

2776

<추가 제출>

2776, 11478, 19583

Copy link

@flowersayo flowersayo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C++ 이 익숙치 않으신데도 문제 최대한 해결해보려고 노력해주셔서 감사합니다 ㅠㅠ
질문 주신 부분은 코드리뷰 커멘트에 남겨놓았으니 참고해주세요!

p1 코멘트는 꼭 수정해주셨으면 하는 부분이고 p2, p3는 읽어보시고 참고하시는 정도로만 받아
들이셔도 좋아요! 물론 p2, p3까지 리팩토링 해주시면 더더욱 좋구요! 아직 풀지 못한 문제들은 오늘 자정이내로 제출해주시거나, 내일까지 샘플코드 모든라인에 주석 달아서 제출해주시면 됩니다! 정말 수고하셨습니다🥰
2776문제 해결하셨거나 궁금한점이 또 생긴다면 저 리뷰어로 호출해주세요~!!

int t, n, m, input;
vector<int> v1, v2;

cin >> t;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 코드가 틀렸습니다! 라고 나오는 일차적인 이유는 전체과정을 t만큼 반복해주는 부분 코드를 작성하지 않았기 때문이에요! 아래 입출력 예시 참고하셔서 한줄만 추가하시면 아마 틀렸습니다! 를 받으시진 않을거에요! 그런데 사실 이문제는 이부분을 고쳐도 맞았습니다! 를 받지 못합니다😢 시간초과가 발생했기 때문인데요! 그 이유는 아래 커멘트 남겨둘테니 참고해주세요!

[입력]

2 //두번 반복
5
4 1 5 2 3
5
1 3 7 9 5
5
4 1 5 2 3
5
1 3 7 9 5

[출력]

1
1
0
0
1
1
1
0
0
1

// 수첩2의 정수가 수첩1에 있는지 확인 (수첩2 정수의 순서대로, 수첩1에 있으면 1, 없으면 0)
for (int i = 0; i < m; i++) {
// 수첩1에 수첩2의 정수가 없을 때 -> 0
if (find(v1.begin(), v1.end(), v2[i]) == v1.end()) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

find함수를 활용해서 수첩1 벡터에서 수첩2의 숫자가 있는지 찾는 방식 식으로 구현방식을 떠올려주신것은 정말 좋아요! 그런데 사실 벡터를 활용하면 시간초과가 발생해서 문제를 해결할 수 없어요!

만약 N의 범위가 작았더라면 작성해주신 방식으로도 문제를 해결할 수 있었을거에요! 그런데 본 문제는 1 ≤ N ≤ 1,000,000 이므로 N이 굉장히 큽니다. 그런데 vector 컨테이너를 사용하게 된다면, 탐색에 소요되는 시간은 O(N)이에요. 모든 원소를 다 뒤져야하니까요! 따라서 수첩2에 존재하는 모든 단어에 대해 수첩1에 있는지 확인해야하니까 이중포문을 돌아야하죠. O(N^2) =1,000,000 * 1,000,000 >>> 2억 이므로 당연히 시간초과가 날거에요! 따라서 숫자찾기를 최대한 빠른 시간 내에 마쳐야합니다!

이를 위해 빠른 탐색을 위한알고리즘 혹은 자료구조를 사용해볼 수 있어요. 방법이 단 한가지만 있지는 않아요! 우선적으로는, algorithm 헤더에 존재하는 시간복잡도가 O(logN)인 이진탐색(binary_search) 을 이용해볼 수도 있구요! map(set) 보다 탐색이 빠른 unordered_map(unordered_set) 을 이용해보실 수도 있어요! 해시 맵의 원리를 이용하기 때문에 key가 유사한 데이터가 많은 것이 아니라면 map(set)보다 더 빠른 탐색을 하기 위한 자료구조로서 유용하게 쓰일 수 있죠! unordered_map(unordered_set)은 해쉬테이블로 구현한 자료구조로 탐색 시간복잡도는 O(1)이에요! Hash 아키텍쳐를 이용하면 탐색, 삽입 , 삭제 모두 O(1)의 시간복잡도를 갖습니다. 혹시 궁금하실까봐 unordered_map 활용법 관련한 링크도 같이 첨부할게요!

https://blog.naver.com/PostView.nhn?blogId=webserver3315&logNo=221678909965&parentCategoryNo=&categoryNo=48&viewDate=&isShowPopularPosts=true&from=search

문제를 푸시다가 "그냥 map 도 이진 트리 구조로서 탐색에 O(logN)의 시간복잡도를 가지지 않나요? binary_search와 시간복잡도가 같은데 왜 map은 시간초과가 나고 binary_search 는 시간초과가 나지 않는지 모르겠어요!" 하고 질문하실 수도 있어요! 그런데 이진트리, 정확히는 RB tree라고 해도 binary search보단 연산이 많아요. 트리 구조 유지를 위한 회전 등, 한번 정렬해두면 끝인 binary search에 비해 계속 삽입과정을 반복하게 되어 map은 시간초과가 발생합니다. 아마 map이 직접 구현한 binary search보다 3~4배정도 느린것 같아요. 따라서 n이 100만일때 O(nlogN)이라면 아슬아슬할거에요. 그래서 탐색을 할때에는 트리를 만들기 보다는 단순하게 이진탐색을 활용해주시는 방법이 훨씬 효율적이고 오버헤드도 적어요! set도 map과 같은 이진트리 구조니 비슷한 결과가 나오겠죠!
+제가 직접해보니 서버상황에따라 set, map으로는 통과할때도 있고 안될때도 있는 것 같아요!

2776, 11478, 19583
@flowersayo
Copy link

추가제출 세문제 확인되셨습니다. 메인에 머지하셔도 좋아요! 수고하셨습니다~!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants