From 1be40e121576e94a08d9bcda5f48966a5ea27966 Mon Sep 17 00:00:00 2001 From: Cho Yin Yong Date: Sat, 24 Oct 2020 00:36:22 -0400 Subject: [PATCH 1/4] Peak of unimodal list DNC algorithm --- divide_and_conquer/peak.py | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 divide_and_conquer/peak.py diff --git a/divide_and_conquer/peak.py b/divide_and_conquer/peak.py new file mode 100644 index 000000000000..257a34e1f1c7 --- /dev/null +++ b/divide_and_conquer/peak.py @@ -0,0 +1,47 @@ +""" +Finding the peak of a unimodal list using divide and conquer. +A unimodal array is defined as follows: array is increasing up to index p, +then decreasing afterwards. (for p >= 1) +An obvious solution can be performed in O(n), +to find the maximum of the array. +(From Kleinberg and Tardos. Algorithm Design. +Addison Wesley 2006: Chapter 5 Solved Exercise 1) +""" +from typing import List + + +def peak(lst: List[int]) -> int: + """ + Return the peak value of `lst`. + >>> peak([1, 2, 3, 4, 5, 4, 3, 2, 1]) + 5 + >>> peak([1, 10, 9, 8, 7, 6, 5, 4]) + 10 + >>> peak([1, 9, 8, 7]) + 9 + >>> peak([1, 2, 3, 4, 5, 6, 7, 0]) + 7 + >>> peak([1, 2, 3, 4, 3, 2, 1, 0, -1, -2]) + 4 + """ + # middle index + m = len(lst) // 2 + + # choose the middle 3 elements + three = lst[m - 1: m + 2] + + # if middle element is peak + if three[1] > three[0] and three[1] > three[2]: + return three[1] + + # if increasing, recurse on right + elif three[0] < three[2]: + if len(lst[:m]) == 2: + m -= 1 + return peak(lst[m:]) + + # decreasing + else: + if len(lst[:m]) == 2: + m += 1 + return peak(lst[:m]) From 51252e0def95fbb21fe58661ae0662953ad693d3 Mon Sep 17 00:00:00 2001 From: Cho Yin Yong Date: Sat, 24 Oct 2020 00:39:56 -0400 Subject: [PATCH 2/4] fix black formatting issues --- divide_and_conquer/peak.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/divide_and_conquer/peak.py b/divide_and_conquer/peak.py index 257a34e1f1c7..8a31b3d0f4ec 100644 --- a/divide_and_conquer/peak.py +++ b/divide_and_conquer/peak.py @@ -28,7 +28,7 @@ def peak(lst: List[int]) -> int: m = len(lst) // 2 # choose the middle 3 elements - three = lst[m - 1: m + 2] + three = lst[m - 1 : m + 2] # if middle element is peak if three[1] > three[0] and three[1] > three[2]: From 5439b18f53d2e4c7b7ded62951a6bca92277393d Mon Sep 17 00:00:00 2001 From: Cho Yin Yong Date: Thu, 29 Oct 2020 22:25:23 -0400 Subject: [PATCH 3/4] add doctest testing --- divide_and_conquer/peak.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/divide_and_conquer/peak.py b/divide_and_conquer/peak.py index 8a31b3d0f4ec..77c91aac3a8a 100644 --- a/divide_and_conquer/peak.py +++ b/divide_and_conquer/peak.py @@ -45,3 +45,8 @@ def peak(lst: List[int]) -> int: if len(lst[:m]) == 2: m += 1 return peak(lst[:m]) + + +if __name__ == "__main__": + import doctest + doctest.testmod() From 34d30198bb327a63f47690199731344e209f65a0 Mon Sep 17 00:00:00 2001 From: Cho Yin Yong Date: Sun, 1 Nov 2020 17:40:18 -0500 Subject: [PATCH 4/4] make file black compliant --- divide_and_conquer/peak.py | 1 + 1 file changed, 1 insertion(+) diff --git a/divide_and_conquer/peak.py b/divide_and_conquer/peak.py index 77c91aac3a8a..f94f83ed3fcb 100644 --- a/divide_and_conquer/peak.py +++ b/divide_and_conquer/peak.py @@ -49,4 +49,5 @@ def peak(lst: List[int]) -> int: if __name__ == "__main__": import doctest + doctest.testmod()