-
알고리즘: 예제를 풀어보자! (feat. 투자의 귀재 규식이)(Brute force, Divide and conquer)알고리즘 2020. 7. 13. 20:04
<투자의 귀재 규식이>
규식이는 친구들 사이에서 투자의 귀재로 알려져 있습니다.
페이스북과 인스타그램에 자신의 성과를 과시하기 때문인데요. 사실 규식이가 그 정도의 실력자는 아닙니다. 성과가 좋을 때에만 SNS에 공유해서 그렇게 비춰질 뿐이죠.
계속해서 멋진 모습을 보여주기 위해, 특정 기간 중 수익이 가장 큰 구간을 찾아내는 함수 sublist_max를 작성해 보려고 합니다.
우선 함수 sublist_max는 파라미터로 며칠 동안의 수익이 담겨 있습니다.
예를 들어서 profits가 [7, -3, 4, -8]이라면 첫 날에는 7달러를 벌었고, 둘째 날에는 3달러를 잃었고, 셋째 날에는 4달러를 벌었고, 마지막 날에는 8달러를 잃은 거죠.
먼저 이 문제를 Brute Force 방법을 이용해서 이 문제를 한 번 풀어봅시다!
1. Brute Force
sublist_max 함수는 profits에서 최대 수익을 내는 구간의 수익을 리턴합니다.
def sublist_max(profits): maximum = profits[0] total = 0 for i in range(0, len(profits) - 1): total = 0 for j in range(i, len(profits)): total += profits[j] maximum = max(maximum, total) return maximum print(sublist_max([4, 3, 8, -2, -5, -3, -5, -3])) print(sublist_max([2, 3, 1, -1, -2, 5, -1, -1])) print(sublist_max([7, -3, 14, -8, -5, 6, 8, -5, -4, 10, -1, 8]))
15 8 27
2. Divide And Conquer
이번에는 같은 문제를 Divide and Conquer 방식으로 풀어보겠습니다. 시간 복잡도는 이 되어야 합니다.
이번 sublist_max 함수는 3개의 파라미터를 받습니다.
- profits: 며칠 동안의 수익이 담겨 있는 리스트
- start: 살펴볼 구간의 시작 인덱스
- end: 살펴볼 구간의 끝 인덱스
sublist_max는 profits의 start부터 end까지 구간에서 가능한 가장 큰 수익을 리턴합니다.
def max_crossing_sum(profits, start, end): # 중간을 지날때 합이 최대가 되는 경우 mid = (start + end) // 2 left_sum = 0 left_max = profits[mid] for i in range(mid, start - 1, -1): # 중간을 기준으로 해서 left부분의 최대합 찾기 left_sum += profits[i] left_max = max(left_max, left_sum) right_sum = 0 right_max = profits[mid + 1] for i in range(mid + 1, end + 1): # 중간을 기준으로 해서 right부분의 최대합 찾기 right_sum += profits[i] right_max = max(right_max, right_sum) return right_max + left_max def sublist_max(profits, start, end): if start == end: return profits[start] mid = (start + end) // 2 left = sublist_max(profits, start, mid) # 최대합이 좌측에 있을경우 right = sublist_max(profits, mid + 1, end) # 최대합이 우측에 있을경우 crossing = max_crossing_sum(profits, start, end) # 최대합이 중간을 가로지를 경우 return max(left, right, crossing) list1 = [-2, -3, 4, -1, -2, 1, 5, -3] print(sublist_max(list1, 0, len(list1) - 1)) list2 = [4, 7, -6, 9, 2, 6, -5, 7, 3, 1, -1, -7, 2] print(sublist_max(list2, 0, len(list2) - 1)) list3 = [9, -8, 0, -7, 8, -6, -3, -8, 9, 2, 8, 3, -5, 1, -7, -1, 10, -1, -9, -5] print(sublist_max(list3, 0, len(list3) - 1)) list4 = [-9, -8, -8, 6, -4, 6, -2, -3, -10, -8, -9, -9, 6, 2, 8, -1, -1] print(sublist_max(list4, 0, len(list4) - 1))
7 28 22 16
3. 시간복잡도 더 단축시키기~
이번에는 시간복잡도를 더 단축시켜 보겠습니다.
처음에 Brute Force로 풀었을 때는 시간 복잡도가
Divide and Conquer를 사용했을 때는 였습니다.
로 한번 더 단축시켜 보겠습니다.
def sublist_max(profits): total = 0 sum_max = profits[0] i = 0 for i in range(0, len(profits)): if total <= total + profits[i] and total < 0: total = 0 total += profits[i] sum_max = max(sum_max, total) return sum_max print(sublist_max([7, -3, 4, -8])) print(sublist_max([-2, -3, 4, -1, -2, 1, 5, -3, -1]))
8 7
한번씩 풀어보세요^^~
문제 출처: 코드잇(Codeit)
반응형'알고리즘' 카테고리의 다른 글
알고리즘: Divide and conquer를 이용한 quick sort 구현 (feat. c++) (0) 2020.09.27 알고리즘: 백준 2565번 전깃줄 (feat. c++) 최장증가수열문제(LIS) (0) 2020.08.31 알고리즘: 그리디 알고리즘(Greedy Algorithm) 공부하고 예제 한번 풀어보자! (0) 2020.07.13 알고리즘: 다이나믹 프로그래밍(dynamic programming) 공부하기! (Memorization, Tabulation, 공간최적화) (1) 2020.07.10 알고리즘: 분할 정복(Divide And Conquer) 예제 공부하기! (합병 정렬, 퀵 정렬) (1) 2020.07.10