diff --git a/docs/source/pydatastructs/linear_data_structures/algorithms.rst b/docs/source/pydatastructs/linear_data_structures/algorithms.rst index 7ab521cfd..a66dc33bb 100644 --- a/docs/source/pydatastructs/linear_data_structures/algorithms.rst +++ b/docs/source/pydatastructs/linear_data_structures/algorithms.rst @@ -45,4 +45,6 @@ Algorithms .. autofunction:: pydatastructs.jump_search -.. autofunction:: pydatastructs.intro_sort \ No newline at end of file +.. autofunction:: pydatastructs.intro_sort + +.. autofunction:: pydatastructs.longest_increasing_subsequence \ No newline at end of file diff --git a/pydatastructs/linear_data_structures/__init__.py b/pydatastructs/linear_data_structures/__init__.py index 057adc169..034702aaf 100644 --- a/pydatastructs/linear_data_structures/__init__.py +++ b/pydatastructs/linear_data_structures/__init__.py @@ -47,6 +47,7 @@ jump_search, selection_sort, insertion_sort, - intro_sort + intro_sort, + longest_alternating_subsequence, ) __all__.extend(algorithms.__all__) diff --git a/pydatastructs/linear_data_structures/algorithms.py b/pydatastructs/linear_data_structures/algorithms.py index 792bce855..a9c0708f7 100644 --- a/pydatastructs/linear_data_structures/algorithms.py +++ b/pydatastructs/linear_data_structures/algorithms.py @@ -30,7 +30,8 @@ 'jump_search', 'selection_sort', 'insertion_sort', - 'intro_sort' + 'intro_sort', + 'longest_alternating_subsequence', ] def _merge(array, sl, el, sr, er, end, comp): @@ -1850,3 +1851,76 @@ def partition(array, lower, upper): intro_sort(array, start=p+1, end=upper, maxdepth=maxdepth-1, ins_threshold=ins_threshold) return array + +def longest_alternating_subsequence(array: OneDimensionalArray, **kwargs) -> int: + """ + Finds the longest alternating subsequence in the given array. + An alternating sequence is one in which the elements are in alternating order, + i.e., a sequence where the differences between consecutive elements alternate + between positive and negative. + + Parameters + ========== + + array: OneDimensionalArray + The array from which the longest alternating subsequence is to be found. + backend: pydatastructs.Backend + The backend to be used. + Optional, by default, the best available backend is used. + + Returns + ======= + + output: OneDimensionalArray + The longest alternating subsequence. + + Examples + ======== + + >>> from pydatastructs import OneDimensionalArray, longest_alternating_subsequence + >>> arr = OneDimensionalArray(int, [1, 5, 4]) + >>> las = longest_alternating_subsequence(arr) + >>> str(las) + '[1, 5, 4]' + >>> arr = OneDimensionalArray(int, [1, 5, 4, 3, 2, 6, 7]) + >>> las = longest_alternating_subsequence(arr) + >>> str(las) + '[1, 5, 2, 7]' + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Longest_alternating_subsequence + + Note + ==== + + The data types of elements in the array should be comparable. + """ + raise_if_backend_is_not_python( + longest_alternating_subsequence, kwargs.get('backend', Backend.PYTHON)) + + # Edge case + if len(array) == 0: + return OneDimensionalArray(int, []) + + increasing = [array[0]] + decreasing = [array[0]] + n = len(array) + + # Iterate from second element + for i in range(1, n): + + # Increasing changes if decreasing changes + if (array[i] > array[i-1]): + increasing = decreasing + [array[i]] + + # Decreasing changes if increasing changes + elif (array[i] < array[i-1]): + decreasing = increasing + [array[i]] + + # Return the maximum length + if len(increasing) > len(decreasing): + return OneDimensionalArray(int, increasing) + else: + return OneDimensionalArray(int, decreasing) diff --git a/pydatastructs/linear_data_structures/tests/test_algorithms.py b/pydatastructs/linear_data_structures/tests/test_algorithms.py index 46609544b..acdf9090a 100644 --- a/pydatastructs/linear_data_structures/tests/test_algorithms.py +++ b/pydatastructs/linear_data_structures/tests/test_algorithms.py @@ -5,7 +5,7 @@ cocktail_shaker_sort, quick_sort, longest_common_subsequence, is_ordered, upper_bound, lower_bound, longest_increasing_subsequence, next_permutation, prev_permutation, bubble_sort, linear_search, binary_search, jump_search, - selection_sort, insertion_sort, intro_sort, Backend) + selection_sort, insertion_sort, intro_sort, longest_alternating_subsequence, Backend) from pydatastructs.utils.raises_util import raises import random @@ -414,3 +414,47 @@ def test_binary_search(): def test_jump_search(): _test_common_search(jump_search) _test_common_search(jump_search, backend=Backend.CPP) + + +def test_longest_alternating_subsequence(): + ODA = OneDimensionalArray + + arr1 = ODA(int, [-4, 3, -5, 9, 10, 12, 2, -1]) + output: OneDimensionalArray = longest_alternating_subsequence(arr1) + expected_result = [-4, 3, -5, 12, -1] + assert str(expected_result) == str(output) + + arr2 = ODA(int, [10, 22, 9, 33, 49, 50, 31, 60]) + output: OneDimensionalArray = longest_alternating_subsequence(arr2) + expected_result = [10, 22, 9, 50, 31, 60] + assert str(expected_result) == str(output) + + arr3 = ODA(int, [1, 2, 3, 4, 5, 6, 7, 8, 9]) + output: OneDimensionalArray = longest_alternating_subsequence(arr3) + expected_result = [1, 9] + assert str(expected_result) == str(output) + + arr4 = ODA(int, [9, 8, 7, 6, 5, 4, 3, 2, 1]) + output: OneDimensionalArray = longest_alternating_subsequence(arr4) + expected_result = [9, 1] + assert str(expected_result) == str(output) + + arr5 = ODA(int, [1, 5, 4, 3, 2, 6, 7]) + output: OneDimensionalArray = longest_alternating_subsequence(arr5) + expected_result = [1, 5, 2, 7] + assert str(expected_result) == str(output) + + arr6 = ODA(int, [1, 5, 4]) + output: OneDimensionalArray = longest_alternating_subsequence(arr6) + expected_result = [1, 5, 4] + assert str(expected_result) == str(output) + + arr7 = ODA(int, []) + output: OneDimensionalArray = longest_alternating_subsequence(arr7) + expected_result = [] + assert str(expected_result) == str(output) + + arr8 = ODA(int, [1]) + output: OneDimensionalArray = longest_alternating_subsequence(arr8) + expected_result = [1] + assert str(expected_result) == str(output)