PGR21.com
- 자유 주제로 사용할 수 있는 게시판입니다.
- 토론 게시판의 용도를 겸합니다.
Date 2010/03/25 00:57:09
Name azurespace
Subject [일반] [해설편] 자료구조와 알고리즘에 대해 생각해 봅시다.
거두절미하고.. 제가 생각한 방법들의 시간복잡도는 다음과 같습니다.

1. 한 번의 쿼리에 대해 처리하는 데 O(1)
2. pre-processing O(N),  한 번의 쿼리에 대해 처리하는 데 O(lg N)
3. pre-processing O(N),  한 번의 쿼리에 대해 처리하는 데 O(lg N)
3. pre-processing O(N),  한 번의 쿼리에 대해 처리하는 데 O(lg N)

메모리 복잡도는 모든 문제에 대해서 O(N)


1번. 정수들의 배열 A가 있습니다. 여러분은 정수 i와 j를 입력받아 A[i]부터 A[j] 사이의 값을 모두 더한 결과(A[i] + A[i+1] + ... + A[j-1] + A[j])를 출력하는 프로그램을 만들어야 합니다. 그런데, 이러한 작업을 cntQuery번 수행해야 한다면 어떤 알고리즘을 사용하겠습니까? 그리고 그 알고리즘의 시간 복잡도는 무엇인가요?

먼저, S[n] = A[1] 부터 A[n]까지의 합이라고 정의합니다.  그러면 A[n] + A[n+1] + ... + A[m-1] + A[m] = S[m] - S[n-1] 입니다. S는 또 다음의 관계가 성립하므로 O(N)만에 구할 수 있습니다. S[n] = S[n-1] + A[n]

2번. 1번과 같습니다. 그러나 이번에는 구하여야 하는 것이 달라졌는데, A[i]와 A[j] 사이에서 가장 큰 값을 찾아 출력해야 합니다. 1번의 알고리즘을 변형시켜 그대로 이용할 수 있습니까? 그렇지 않다면 어떤 알고리즘을 이용해야 할까요?

1번과 같은 방법으로 접근해서는 금방 반례에 도달하게 됩니다. 어떤 경우냐면, 사용자가 입력한 쿼리의 범위보다 global minimum이 앞에 있는 경우입니다. 금방 발견할 수 있죠.

어떻게 풀 수 있는지는 3,4번 문제와 같이 설명하겠습니다.

3번. 1번과 같습니다. 그러나 고객이 새로운 요구사항을 추가했습니다. 그것은 배열의 내용을 변경시키고 싶다는 것입니다. 그래서 여러분은 고객이 음수인 i를 입력하였을 경우 A[-i] = j가 되도록 하겠다고 약속했습니다. 이 경우에도 1번의 알고리즘을 사용할 수 있나요? 그렇지 않다면 대안은 무엇입니까?

당연히 1번 알고리즘을 사용할 수 없습니다. A[n]의 값이 변하면 S[n], S[n+1], ... 의 값도 같이 변해야 합니다. 이 과정에서 한 번의 대입과정이 O(N)이 되어버리므로, 하지 않느니만 못할 수 있습니다.

4번. 다른 모든 조건은 3번 문제와 같지만, 구하여야 하는 것은 2번과 같습니다. 이 경우는 어떻게 됩니까?
2,3번과 같은 자료구조를 이용하면 쉽게 풀립니다.


Interval tree를 알고 계십니까? 컴퓨터 과학을 전공하신 분들은 우리말로 구간 나무라고 하기도 하는 이 자료구조에 대해 한 번쯤은 들어본 듯한 기억도 있을 겁니다. CLRS를 보시면 잘 설명되어 있습니다.

간단한 컨셉트를 설명드리면, 이 트리는 기본적으로 Binary Search Tree와 같습니다. 하지만 다른 점이 있다면, 각 노드가 지니고 있는 것은 특정 키 값이 아니라, 어떤 정수 구간입니다. 그리고 이 구간의 사이에 해당 노드의 자손들의 구간이 들어가게 됩니다. [1, 2] 구간을 지닌 노드와 [3,6] 구간을 지닌 노드가 [1,7] 구간을 지닌 노드의 자손으로 들어갈 수 있는 셈입니다.BST의 구간 버전이기 때문에 노드 하나를 삽입하거나 삭제하는데 필요한 비용은 O(lg N)입니다.

이해가 잘 안 되는 분들은 : http://en.wikipedia.org/wiki/Interval_tree 을 참고하시길 바랍니다.

이 트리를 어떻게 하면 이들 문제를 풀기 위해 적용할 수 있을까요? 노드에 값 필드 하나를 추가합니다. 그리고 이 값이 구간 전체의 대표값이 되도록 하는 겁니다. 예를 들어 2번 문제에서 어떤 노드가 나타내는 구간이 [1, 5]이고 대표값이 8이라면, A[1]부터 A[5]까지의 합이 8인 겁니다.

이 인터벌 트리를 일단 구성하면 특정 위치의 값을 변경하는 것은 간단합니다. a[n] = b라는 쿼리가 주어졌다면, [n,n] 구간을 나타내는 노드를 O(lg N) 만에 찾아서, 뿌리 노드까지 올라가면서 대표값을 바르게 갱신하면 됩니다. 이진 탐색 트리이므로 트리의 깊이는 O(lg N)입니다. 따라서 대입 연산의 전체 시간 복잡도가 O(lg N)이 됩니다.

임의의 구간이 주어졌을 때 그 구간 내부에 해당하는 모든 노드를 찾는 연산은 Interval Tree 자체를 공부하시면 나옵니다. 이를 약간 고쳐서 고객이 요구한 답을 찾을 수 있어요. [1, 6] 구간의 대표값을 알고 있다면, [1,3] 구간이나 [4,6] 구간의 대표값을 굳이 알아야 필요가 없겠지요? 이 과정에서는 2 * lg N개 이상의 노드가 필요하지 않습니다. 이 역시 O(lg N)입니다.


그리고 이 Interval Tree를 기반으로 몇 가지 편리한 특성을 추가한 자료구조가 있습니다. 컴퓨터 과학을 전공한 사람이라도 이 자료구조에 대해서는 잘 모르는 경우가 많습니다. 저 같은 경우 Binary Cache Tree라고 부릅니다만 Indexed Tree 라고 부르는 사람도 있고, Hash Tree라고 부르는 사람도 있습니다. 그러나 뭐.. 그냥 Interval tree라고 볼 수도 있겠습니다.

Interval Tree를 사용하는 일반적인 문제들은 대체로 그렇지 않습니다만, 이번에 제가 낸 문제는 배열의 모든 인덱스 각각에 대해서 노드 하나씩을 반드시 사용해야 합니다. 이 경우 Interval Tree는 Binary Tree이므로 Complete Tree가 됩니다. 그렇다면 이 트리를 구현하기 위해 포인터를 포함한 복잡한 구조체를 작성한다거나 할 필요가 있을까요?

Complete Binary Tree를 이용하는 자료구조의 전형적인 예가 있습니다. 바로 Heap입니다. Heap 구현하실 때 트리구조를 나타내기 위해 무엇을 이용합니까? 배열이죠. 마찬가지로 배열을 이용해 이 자료구조를 구현하면 다음과 같은 편리한 특성들을 얻을 수 있습니다.

1. N개의 데이터가 미리 주어져 있을 때, 이 데이터를 Tree에 모두 삽입하는 데 걸리는 시간복잡도는 O(N lg N)이 아닌 O(N)입니다. 맨 아래 레벨에 미리 채워두고 나머지 칸을 거꾸로 순회하면서 해당 노드의 대표값을 구할 수 있습니다.
2. 어떤 노드가 부모의 왼쪽 자식인지, 오른쪽 자식인지를 나머지 연산으로 구할 수 있습니다.
3. N = 2 ^ k이면, 필요한 배열의 크기는 2*N입니다.
4. 코딩이 간단하고 편리합니다.
5. 각 노드가 자신이 나타내는 구간의 시작과 끝을 굳이 저장하고 있을 필요가 없습니다. 뿌리 노드가 나타내는 구간의 크기는 1이고, 그 윗 레벨에서는 2입니다. 또 그 위의 레벨에서는 4죠. 이러한 관계로부터 알아낼 수 있습니다.


알고리즘과 자료구조는 공부하면 할 수록 재미있는 분야입니다. 프로그래밍을 해 본 사람들만이 느낄 수 있는 즐거움이 있어요. 저는 지금까지 공부하면서 재밌다고 느낀 것은 얘들 뿐입니다. 여러분도 한번 그 재미를 느껴 보세요.

통합규정 1.3 이용안내 인용

"Pgr은 '명문화된 삭제규정'이 반드시 필요하지 않은 분을 환영합니다.
법 없이도 사는 사람, 남에게 상처를 주지 않으면서 같이 이야기 나눌 수 있는 분이면 좋겠습니다."
10/03/25 01:21
수정 아이콘
흐흐.. 저도 머리가 많이 굳었나 봅니다. 아뭏든 덕분에 꽤나 즐거웠습니다.
정작, 오늘 하려던 업무는 망쳐버렸지만요.. 엉엉... ㅠㅠ

P.S: 아.. 결론은 트리였군요...;;
그러고보니, 저도 이번기회에 공간분할 트리 구조나 좀 더 손봐야겠습니다. 아무리 생각해도 전에 만든게 너무 무성의해서...
10/03/25 01:57
수정 아이콘
읽어도 1번이 어떻게 O(1)이 되는가 알수 없네요-_-;;;
10/03/25 02:19
수정 아이콘
근데.. 저라면, 3번 문제에 대해서는, 대입할때... 대입한 항의 원래 값과 대입된 값의 차를 구해서,
S[n~m] 배열의 값을 일괄적으로 변경시켜주고, 합을 구할때는 1번과 같은 방식으로 계산하는 방식을 쓰겠습니다.
대입 연산이 O(N)이 되고, 합 연산은 O(1)이 되지만, 트리를 서치할때 쓰이는 나누기와 나머지 연산이 꽤나 무겁거든요...

실전에서도, O(N^2)의 알고리즘보다 O(N^3)의 알고리즘이 오히려 빠른 경우도 종종 있어요. ^^;;;
뭐, 그냥 머리속으로 생각만 해본거라, 실제 구현해보면 결과가 다를 수도 있겠죠.
Je ne sais quoi
10/03/25 07:33
수정 아이콘
저도 재미있게 했습니다. 그래서 야근만 하고 일을 안 했네요 -_-;;
10/03/25 09:00
수정 아이콘
분명히 트리가 답일 거라고는 생각했는데 어떻게 인덱싱하고 범위검색을 할지 떠오르지가 않았네요..;
(B-Tree로 인덱싱하고 범위검색하면 복잡도가 얼마였더라 고민하기도 했다는..;;)
인터벌 트리가 있었군요. (알고리즘 시간에 배워놓고 까먹었다는..)
10/03/25 09:01
수정 아이콘
저는 개발일로 밥먹고 사는 사람입니다만 답은 고사하고 문제 자체가 무슨 말인지를 모르겠습니다.

알고리즘이라는 것도 중요하긴 하지만 실제로 IT 현장에서는 알고리즘은 그렇게 중요한 부분은 아닙니다. 시스템 프로그래머나 게임, 엔진 개발자들에겐 필요한 부분이겠지만요.

일반적인 IT 현장에서는 저런 디테일 보다는 업무 분석과 DB 설계, 프레임 워크, 시스템 디자인 등이 훨씬 중요한 요소죠. 스스로 새로운 알고리즘을 고민해야 할 경우는 거의 없습니다.

태클 걸려는 건 아니고 저런 거 모르면 개발자 하면 안되는 건가 하고 좌절하실 분이 있을까 봐 드리는 말씀입니다. ^^
10/03/25 14:32
수정 아이콘
근데, 2,3,4번 문제에

preprocessing이 indexed tree를 construction 하는건데 그렇담 시간 복잡도는 O( nlogn ) 아닌가요?

링크된 문서에 따르면

"Queries require O(log n + m) time, with n being the total number of intervals and m being the number of reported results. Construction requires O(n log n) time, and storage requires O(n) space."

라고 나와있는데요.
10/03/25 14:43
수정 아이콘
그리고 azurespace님 지금이야 전공이 아니셔서 관련 과목을 안듣고 계시는걸로 알고 있는데,

대학 들어오기 전에 꽤 오랜기간동안 알고리즘이랑 자료구조에 대해 많이 공부하신걸로 알고있는데 아닌가요?

"조금만 공부하면 저만큼 할 수 있어요"는 좀 어폐가 있다고 봅니다. 다시 말하자면, azurespace님 만큼의 실력을 가질려고 newbie가 지금부터 공부를 한다면 꽤 오랜 기간이 걸릴꺼라 생각합니다.

그리고 혹시나 자료구조나 알고리즘 이런곳에 관심이 있으신분들이라면 http://algospot.com 에 한번 들어와보세요(홍보글로 판단되어 짤린다면 수정을 하겠습니다.) 이곳은 제가 운영진으로 있는( 그리고 azurespace님도 활동하시는걸로 알고 있는 ^^ ) Programming 경시대회 관련 사이트인데, 아마 자료구조나 알고리즘을 열심히 공부하고싶어! 생각하시는 분들께 많이 도움이 될거라 생각합니다.
arq.Gstar
10/03/25 18:41
수정 아이콘
다음엔 Java 개발에 관련된 이약를 해주시는 선배님이 있으셨으면 좋겠어요..^^
목록 삭게로! 맨위로
번호 제목 이름 날짜 조회 추천
20528 [일반] 거꾸로가는 한국.. [10] ad8154593 10/03/25 4593 0
20527 [일반] 애프터 스쿨의 신곡 "Bang!"도 공개되었네요. (뮤직비디오 추가합니다) [25] 세우실4703 10/03/25 4703 0
20525 [일반] 러브포보아의 Core i3 530 필드테스트 한 것 자료 올려보바요~ [11] 러브포보아3936 10/03/25 3936 0
20524 [일반] 브라운 아이드 소울의 신곡이 공개되었습니다. [22] 세우실4626 10/03/25 4626 0
20523 [일반] [피겨]세계선수권대회가 진행 중 입니다. [20] 달덩이3707 10/03/25 3707 0
20522 [일반] 개인적으로 추천하는 2009년 걸그룹 무대동영상 1탄 [19] let8pla7949 10/03/25 7949 0
20521 [일반] 3월 31일 수목드라마 예고편 [34] 우아한페가수5119 10/03/25 5119 0
20520 [일반] I'll be there [4] Xell0ss4364 10/03/25 4364 0
20519 [일반] 스타킹 출연하셨던 소향님 다른 무대 둘 [5] Xell0ss4123 10/03/25 4123 0
20518 [일반] 스타킹 출연하셨던 소향님 다른 무대 하나 [11] zeros4974 10/03/25 4974 0
20517 [일반] 어제 낮에 병점에서 잠깐 정전이 있었습니다 이와 동시에 기흥에 삼성에서도 정전이..... [18] 귀여운마제곰4167 10/03/25 4167 0
20516 [일반] [해설편] 자료구조와 알고리즘에 대해 생각해 봅시다. [30] azurespace5052 10/03/25 5052 0
20515 [일반] 내가생각하는 대한민국 아이돌 최고의 안무 [91] 소녀시대김태10667 10/03/24 10667 0
20514 [일반] [쓴소리]대한민국 사시면서 살림살이 좀 나아지셨습니까(1)?? [38] 영웅과몽상가4218 10/03/24 4218 0
20512 [일반] [예능이야기]청춘불패와 천하무적야구단. [26] Hypocrite.12414.7247 10/03/24 7247 4
20511 [일반] 무법자감상(스포스포열매) [3] 부엉이3725 10/03/24 3725 0
20510 [일반] [음악] 야밤에 이런 음악..? (6) [15] 코리아범3463 10/03/24 3463 1
20509 [일반] 쇼트트랙 빙상연맹 밥그릇 싸움 문제가 다시 불거졌네요 [21] Jess4338 10/03/24 4338 0
20508 [일반] 인터넷 악플러 때문에 경찰서에 고소 하고 왔습니다... (有) [40] Eva0105959 10/03/24 5959 0
20507 [일반] 2010 챔피언스리그 4강전 경기를 관람하게 됐습니다~! [35] 질롯의힘4658 10/03/24 4658 0
20506 [일반]  KBS.MBC "월드컵 공동중계 성사안되면 K리그 중계 안하겠다" [43] 반니스텔루이5281 10/03/24 5281 1
20505 [일반] [문제편] 자료구조와 알고리즘에 대해 생각해 봅시다. (문제 순화하였습니다.) [54] azurespace3257 10/03/24 3257 0
20503 [일반] 가수 이성진 사기혐의로 청주에서 긴급체포, 개그맨 김태현 폭행혐의로 입건 [42] 권보아14042 10/03/24 14042 0
목록 이전 다음
댓글

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