PGR21.com
- 자유 주제로 사용할 수 있는 게시판입니다.
- 토론 게시판의 용도를 겸합니다.
Date 2013/04/14 03:06:30
Name azurespace
Subject [일반] 알고리즘 문제와 그 풀이 #1. Sliding Window

알고리즘 문제를 해결하는 것이 목표인 대회들이 있습니다. 대표적으로는 국제정보올림피아드(IOI)가 있으며 여기에 참여할 국가대표를 뽑기 위한 한국정보올림피아드(KOI), 그 외에도 ACM-ICPC, Topcoder, Codechef 등 여러 오프라인 및 온라인 대회들이 있습니다. 오늘 진행된 구글 코드잼 같은 대회는 성적에 따라서 구글에서 채용하기도 할 정도지요


제가 풀어본 문제들 중 몇가지를 올리고 제가 어떻게 풀었는지 한번 경험을 공유해보고자 합니다.



시간제한: 12초
테스트 케이스당 시간 제한 : 5초
메모리 사용량 제한 : 65536KB


여기 배열이 하나 있습니다 배열의 크기는 n으로 10^6 넘지 않습니다그리고  배열의 왼쪽 끝에서 오른쪽 끝으로 움직이고 있는 슬라이딩 윈도우가 있습니다 윈도우의 길이는 k입니다여러분은 윈도우 안에 보이는 k개의 수만을   있습니다윈도우는  번에  칸씩 오른쪽으로 움직입니다다음은 예제입니다.

 예제는 원문 출처로 가서 보시기 바랍니다.

문제 출처 :  http://poj.org/problem?id=2823



슬라이딩 윈도우가  위치에 있을  보이는 최대값과 최소값이 무엇인지 구하는 것이 여러분에게 주어진 문제입니다.




입력

입력은  개의 줄로 이루어져 있습니다 번째 줄은 배열의 길이와 슬라이딩 윈도우의 길이를 나타내는  개의 정수n k 담고 있습니다다음 줄에 배열의 내용을 나타내는 n개의 정수가 담겨 있습니다.



출력

출력은  개의 줄을 담고 있어야 합니다 번째 줄은 윈도우가 왼쪽에서 오른쪽으로 움직일 때마다 윈도우에 보이는 최소값을 나타냅니다두번째 줄은 최대값입니다.









 



주의 : 지금부터는 이 문제의 풀이입니다. 직접 문제를 풀어보고 싶으신
분들은 읽지 말아주세요. 스포일러 방지 기능이 있으면 좋을텐데 없군요.



Naïve Solution

가장 간단한 풀이는 각 위치에 대해서 슬라이딩 윈도를 직접 대어 보고 최대값과 최소값이 무엇인지 찾는 것입니다. 2중 for문을 통해서 구현하면 되겠죠. O(NK)입니다


소스 코드 : http://ideone.com/c0bBrQ



하지만 이 풀이는 너무나 느립니다. N의 크기가 1000000까지 될 수 있고 K도 마찬가지이므로 이런 경우에는 아무리 코드를 최적화한다 하더라도 시간내에 답이 나오지 않습니다. 


Min-max Heap



 



Heap이라는 자료구조가 있습니다. 이 자료구조의 한 변형인 Min-max Heap은 현재 Heap 안에 들어있는 원소들 중 최소값과 최대값이 무엇인지 상수 시간에 알 수 있으며, 하나의 원소가 삽입되고 제거될 때마다 O(lg N)만큼의 연산이 소요됩니다. (Deap이라는 변형에서도 가능합니다) 그런데 이때 최대값과 최소값 이외의 모든 값에 대해서 어느 위치에 있는지를 하나하나 추적하게끔 구현할 수 있습니다. N의 최대값은 백만인데, 백만개 정도 정수배열을 하나 더 잡는다고 해서 메모리 경계를 초과하지는 않습니다.



 



그러므로 Min-max heap이나 Deap을 사용해서 슬라이딩 윈도우가 오른쪽으로 이동할 때마다 추가되는 수를 자료구조에 집어넣고, 빠져나가는 수를 자료구조에서 빼는 식으로 구현할 수 있습니다. 이렇게 한 경우 시간복잡도는 O(N lg N)입니다. 충분히 시간 내에 나올 수 있지요. 그런데 일반적으로 구현된 라이브러리에는 min, max를 제외한 다른 원소를 추적하는 기능이 없습니다. 어쩔 수 없죠. 원래 그걸 위한 자료구조가 아닌걸요… 직접 구현하는 수밖에 없습니다. 이 방법에 대해서는 따로 코드를 첨부하지 않겠습니다.



 Binary-search Tree


이진 탐색
트리는 이진 트리의 일종으로 각 노드의 왼쪽 자식은 부모 노드가 지닌 값보다 작은 값을 지니고, 오른쪽 자식은 부모보다 큰 값을 갖도록 구성되어 있습니다. 균형잡힌 이진 트리의 경우 데이터의 삽입, 삭제가 O(lg N)만에 가능합니다.
 



그리고 중요한 특징은, 이진 탐색 트리의 최소값과 최대값 역시 O(lg N)에 구할 수 있다는 것입니다. 이 방법 역시 O(N lg N)에 해결이 가능합니다.


소스 코드 : http://ideone.com/V3anCU



Indexed Tree

인덱스 트리라는 자료구조는 완전 이진 트리의 일종인데, 알고리즘 경시에
참여하는 사람들 사이에서 통용되는 이름입니다. 구간 트리라고도 불리는데 일반적인 구간 트리와는 약간
다릅니다.



일단 이 트리는 완전 이진 트리이므로 .N보다 크거나 같은 가장 작은 2의 지수를 M이라 할 때,
2*.M개의 저장공간을 필요로 합니다.


각 노드는 자신이 가리키는 구간을 ‘대표하는’ 값을 지니게 됩니다. 예를 들어 이 문제의 경우 트리의 루트 노드는 Min( Array[0..M-1] ) 또는 대응되는 Max의 값을 가지게 되겠죠. 루트의 왼쪽 노드는 0 ~ M/2-1까지의 구간을 대표하고, 루트의 오른쪽 노드는 M/2 ~ M-1까지를
대표하고.. 이런 식으로 깊이가 한단계 깊어질 때마다 노드가 대표하는 구간의 크기가 절반씩 줄어듭니다. 깊이가 log M이 되면 각각 길이 1의 구간을 대표하고 있게 되죠. (그 위치에 해당하는 Array의 값을 지닌다는 뜻)



 



트리의 갱신은 일단 가장 끝부분의 값을 바꾸고, 부모 노드를 하나씩
타고 올라오면서 값을 갱신해 줍니다. 두 자식의 값을 보고 자기자신을 바꾸는 recursive 함수를 작성하면 되겠죠?



이렇게 하면 임의의 구간에 대한 값을 구하는 건 lg M 개의 노드만 선택하면 어떤 구간이라도 커버가 가능하기 때문에… O(lg M) = O(lg N)입니다. M < 2*N이니까요. 





지금까지 O(N lg N) 솔루션을 보았습니다. 그런데… 사실 이 문제를 해결하는 가장 빠른 알고리즘의 시간복잡도는 O(N)입니다. 믿기시나요?



일단 배열을 2*K-1개씩 쪼갭니다.
K=4이라면 배열을 7개 단위로 자르게 되겠네요. 다음을 봅시다.


A[0]  A[1]   A[2]   A[3]   A[4]  A[5]   A[6]


이때 중앙에서부터 계산을 시작하면 다음과 같은 배열은 O(K)만에
계산이 가능하겠죠?



Min[0..3] Min[1..3] Min[2..3] A[3] Min[3..4] Min[3..5] Min[3..6]


그런데 이걸 잘 보시면요. 이 배열만으로 슬라이딩 윈도우 내에서 최소값이
무엇인지 다 알 수 있어요.


Min[0..3]은 배열 안에 있고요. Min[1..4] = Min[1..3]과 Min[3..4] 중 작은 값이죠.
Min[2..5]는 Min[2..3]과 Min[3..5]중에 작은 값이죠…

어헣 간단하죠?


2*K-1개씩 배열을 나누면 대충 O(N/K)개의 부분배열이 나오죠? 각각의 부분배열에서 최대값과 최소값을 구하는 것은 O(K)만에 되니까 O(N/K) * O(K) = O(N) 이 되는 것입니다.



코드 : http://ideone.com/sduj2J


이 코드는 2007년에 제가 고딩이었던 시절에 작성한 거라 좀 더럽긴 한데 뭐 방법 자체는 충실히 구현하고 있습니다.



 


생각보다 길어졌네요. 과연 시리즈물로 찾아뵐 수 있을는지?


통합규정 1.3 이용안내 인용

"Pgr은 '명문화된 삭제규정'이 반드시 필요하지 않은 분을 환영합니다.
법 없이도 사는 사람, 남에게 상처를 주지 않으면서 같이 이야기 나눌 수 있는 분이면 좋겠습니다."
꿀호떡a
13/04/14 03:07
수정 아이콘
우와 피지알에 알고리즘글이....
13/04/14 03:54
수정 아이콘
재미있게 읽었습니다, 알고리즘의 세계는 무궁무진하군요.
전전에서 컴공으로의 대학원 진학을 생각하는 입장에서, 이런 문제들을 기발한 알고리즘으로 풀어내는 사람들을 보면
존경심과 동시에, 이런 똑똑한 사람들도 있는데 제가 컴공을 하겠다는 게 분수에 맞는 것인가 하는 불안감도 들곤 합니다.

제가 잘 이해하지 못한 것이겠지만... 질문 있습니다.
k가 4이고 고로 7로 배열을 자른다고 하였을 때,
(Min[0..3] Min[1..3] Min[2..3] A[3] Min[3..4] Min[3..5] Min[3..6]) (Min[7..10] Min[8..10] Min[9..10] A[10] Min[10..11] Min[10..12] Min[10..13]) (...)
제가 이해한 대로라면 이렇게 배열이 잘리게 될텐데요,
Min[0..3], Min[1..4], Min[2..5], Min[3..6], 즉 한 "조각" 내에서 최소치를 구하는 것은 두 원소 비교만 하면 되니 자명한데,
Min[4..7], Min[5..8], Min[6..9] 등 두 조각에 걸쳐있는 경우에서 최소치를 구하는 방법은 어떻게 하나요?
앞 네 원소와는 다르게 두 원소 비교만으로는 힘들 것 같아서요.
레필리아
13/04/14 10:34
수정 아이콘
전전에서 컴공 오시는거면.. 하드웨어의 세계로 오시는게 어떨까요??
13/04/14 22:38
수정 아이콘
아키나 임베디드 쪽 말씀하시는 건가요...사실은 머신러닝쪽 생각하고 전과를 결심한 거라서요. 흐흐
azurespace
13/04/14 04:26
수정 아이콘
4로부터 시작하는 2k-1크기 부분배열을 다시 만듭니다 그러니까 부분배열의 시작 인덱스는 k씩 증가하게 되겠지요
태연O3O
13/04/14 04:50
수정 아이콘
재미있게 봤습니다.
신밧드
13/04/14 09:01
수정 아이콘
재미있게 보고싶습니다..
외계어군요
2막2장
13/04/14 09:25
수정 아이콘
학부 전자에 석사 영상처리 전공이라 sliding window가 익숙해서 봤더니, 알고리즘 분야였군요 ㅠㅠ
꽤 다양한 해법이 존재하네요. 성능은 천차 만별이고.. 잘 보고 갑니다.
13/04/14 10:11
수정 아이콘
저와같으시네요.

어느쪽하시는지 크크
13/04/14 09:29
수정 아이콘
트리같은 자료구조쓰면 nlogk아닌가요?
슬라이딩 윈도우보다 많은 크기의 원소를 가질 필요가 없어보이는데요
azurespace
13/04/14 12:47
수정 아이콘
네 맞습니다 뭐 lg n >= lg k라 O표기법으로 틀린건 아니에요 (...)
목록 삭게로! 맨위로
번호 제목 이름 날짜 조회 추천
99568 [정치] 대통령실, ‘오염수 안전’ 영상 직접 주도…예산부터 제작까지 [76] 베라히10509 23/08/22 10509 0
99567 [정치] 與지도부 “총선 수도권 승산, 1당도 무난”… 수도권 의원들 “위기의식 부족한 게 위기” [173] 기찻길13557 23/08/22 13557 0
99566 [일반] 저출산 시대 어메이징한 한국의 되팔이 [67] 빼사스8279 23/08/22 8279 1
99565 [일반] 서이초 '연필사건' 가해 학부모는 현직 경찰과 검찰 수사관 [57] 검사11111 23/08/22 11111 7
99564 [일반] 제트스키 밀입국 중국인의 정체(확인중) [49] Life's Too Short10667 23/08/22 10667 0
99563 [정치] 윤석열 대통령 “北, 개전 초부터 반국가세력 활용 선전선동”···전쟁 준비 강조 [151] 베라히14378 23/08/22 14378 0
99561 [정치] 건설용역 전관업체와 맺은 648억 규모 계약 전면 백지화 [39] rclay9443 23/08/22 9443 0
99560 [정치]  사단장 제외 반발‥대대장 측 "혼자 지시 안 했다" [97] 기찻길14917 23/08/21 14917 0
99559 [일반] 오펜하이머 관람 후기. 이런 취향인 사람은 강추, 이런 취향인 경우 매우 비추 (노스포) [65] Quantumwk8421 23/08/21 8421 1
99558 [정치] NHK "이르면 24일 오염수 방류 개시"... 기시다, 어민 반대에도 강행 [31] 검사7349 23/08/21 7349 0
99557 [정치] 진중권 "이동관 후보자, MB때 괴벨스 노릇했던 사람" [78] 베라히11049 23/08/21 11049 0
99556 [일반] LH아파트 철근조사 부실 기둥에 철근이 있는데 없다고 발표 [61] DownTeamisDown16957 23/08/21 16957 5
99555 [정치] 한미일 안보협의체가 만들어졌습니다 [144] rclay16033 23/08/21 16033 0
99553 [일반] 제 105회 고시엔 이야기 - 4강팀 결정 [28] 간옹손건미축4983 23/08/21 4983 3
99552 [일반] 말리지 마세요 - 달짝지근해 [16] 새님6935 23/08/21 6935 10
99551 [정치] 새만금 사업을 막아야 하는 이유 [27] Beemo10881 23/08/20 10881 0
99549 [일반] 오펜하이머 보고 생각나는대로 주절주절.. (스포) [24] 유료도로당6014 23/08/20 6014 4
99548 [일반] 뉴욕타임스 8.15. 일자 기사 번역(중국 부동산업체 컨트리가든의 위기) [22] 오후2시7369 23/08/20 7369 4
99547 [일반]  K-POP을 이용해 일본인 관광객들을 포교하는 신천지 [15] 기찻길8390 23/08/20 8390 1
99546 [정치] 진중권, 윤 정부 두고 "이명박·박근혜보다 더 심해…속았다는 느낌 든다" [110] 베라히13319 23/08/20 13319 0
99545 [일반] 야 정몽주1! [29] seotaiji6484 23/08/20 6484 2
99543 [일반] 직장인이 되고 나서 해본 공부 [12] rclay7120 23/08/20 7120 9
99542 [일반] [팝송] 제이슨 므라즈 새 앨범 "Mystical Magical Rhythmical Radical Ride" [2] 김치찌개4478 23/08/20 4478 0
목록 이전 다음
댓글

+ : 최근 1시간내에 달린 댓글
+ : 최근 2시간내에 달린 댓글
맨 위로