Skip to content

Added Longest Increasing Subsequence #336

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e882023
Added Longest Increasing Subsequence
tanyarajhans Feb 27, 2021
1cc929b
Added LIS
tanyarajhans Feb 27, 2021
1ee32a6
Updated test_algorithms.py
tanyarajhans Feb 27, 2021
1dd7734
Updated __init__.py
tanyarajhans Feb 27, 2021
63beb7f
Fixed errors
tanyarajhans Feb 27, 2021
a85ba89
Fixed errors
tanyarajhans Feb 27, 2021
5ca042f
Fixed errors
tanyarajhans Feb 27, 2021
9c88875
Fixed errors
tanyarajhans Feb 27, 2021
e153637
Fixed errors
tanyarajhans Feb 27, 2021
78c97d5
Fixed errors
tanyarajhans Feb 27, 2021
613c5aa
Fixed errors
tanyarajhans Feb 27, 2021
2be1290
Fixed errors
tanyarajhans Feb 27, 2021
e53706b
Fixed errors
tanyarajhans Feb 27, 2021
3ed9d54
Fixed errors
tanyarajhans Feb 27, 2021
bd7c943
Fixed errors
tanyarajhans Feb 27, 2021
cfc51d2
Fixed errors
tanyarajhans Feb 27, 2021
167fd7e
Fixed errors
tanyarajhans Feb 27, 2021
7a4c2bc
Fixed errors
tanyarajhans Feb 27, 2021
f3bc1d6
Fixed errors
tanyarajhans Feb 27, 2021
fa482ea
Fixed errors
tanyarajhans Feb 27, 2021
3ce0a31
Fixed errors
tanyarajhans Feb 27, 2021
9b28143
Fixed errors
tanyarajhans Feb 27, 2021
cb1f85c
Restored lines
tanyarajhans Feb 28, 2021
99066c5
Update algorithms.py
tanyarajhans Feb 28, 2021
86e0d84
NlogN approach for LIS
tanyarajhans Feb 28, 2021
6fdef7a
Indentation fixed
tanyarajhans Feb 28, 2021
2adf931
Update algorithms.py
tanyarajhans Feb 28, 2021
9fb7ba2
Update algorithms.py
tanyarajhans Feb 28, 2021
d5c40e1
Update algorithms.py
tanyarajhans Feb 28, 2021
09cf057
Update pydatastructs/utils/tests/test_code_quality.py
tanyarajhans Feb 28, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion pydatastructs/linear_data_structures/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
bucket_sort,
cocktail_shaker_sort,
quick_sort,
longest_common_subsequence
longest_common_subsequence,
longest_increasing_subsequence
)
__all__.extend(algorithms.__all__)
65 changes: 64 additions & 1 deletion pydatastructs/linear_data_structures/algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
'bucket_sort',
'cocktail_shaker_sort',
'quick_sort',
'longest_common_subsequence'
'longest_common_subsequence',
'longest_increasing_subsequence'
]

def _merge(array, sl, el, sr, er, end, comp):
Expand Down Expand Up @@ -787,3 +788,65 @@ def longest_common_subsequence(seq1: OneDimensionalArray, seq2: OneDimensionalAr
check_mat[i][j] = check_mat[i][j-1]

return OneDimensionalArray(seq1._dtype, check_mat[row][col][-1])

def longest_increasing_subsequence(seq: OneDimensionalArray) -> int:
Copy link
Member

@czgdp1807 czgdp1807 Feb 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function currently returns only the length. There should be a possibility of obtaining the longest increasing sub-sequence as well.

For example, if ODA([1, 2, -1, 3, 4, 5]) is the input then, (ODA[1, 2, 3, 4, 5], 5) should be the output. Specifically, the first element of the tuple is the LIS and the second is it's length though returning only the sequence will suffice.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"""
Finds the length of longest increasing subsequence of the given sequences.
Parameters
========
seq: OneDimensionalArray
The sequence.
Returns
=======
output: int
The length of longest increasing subsequence.
Examples
========
>>> from pydatastructs import longest_increasing_subsequence as LIS, OneDimensionalArray as ODA
>>> arr1 = [1, 3, 9, 4, 6]
>>> lis = LIS(arr1)
>>> str(lis)
'4'
>>> arr1 = [8, 7, 2, 12, 16, 28, 44]
>>> lis = LIS(arr1)
>>> str(lis)
'5'

References
==========
.. [1] https://en.wikipedia.org/wiki/Longest_increasing_subsequence

"""
def CeilIndex(A, l, r, key):
while (r - l > 1):
m = l + (r - l)//2
if (A[m] >= key):
r = m
else:
l = m
return r
Comment on lines +820 to +827
Copy link
Member

@Smit-create Smit-create Mar 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just define and use methods or functions on sorted ODA for finding lower_bound and upper_bound (similar to how it works in cpp)? Instead of defining such private functions?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just define and use methods or functions on sorted ODA for finding lower_bound and upper_bound (similar to how it works in cpp)?

Sure.


size = len(seq)
tailTable = [0 for i in range(size + 1)]
length = 0 # always points empty slot

tailTable[0] = seq[0]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use snake case and not camel case.

length = 1
for i in range(1, size):
if (seq[i] < tailTable[0]):

# new smallest value
tailTable[0] = seq[i]
elif (seq[i] > tailTable[length-1]):

# seq[i] wants to extend
# largest subsequence
tailTable[length] = seq[i]
length+= 1
else:
# seq[i] wants to be current
# end candidate of an existing
# subsequence. It will replace
# ceil value in tailTable
tailTable[CeilIndex(tailTable, -1, length-1, seq[i])] = seq[i]
return length
26 changes: 24 additions & 2 deletions pydatastructs/linear_data_structures/tests/test_algorithms.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from pydatastructs import (
merge_sort_parallel, DynamicOneDimensionalArray,
OneDimensionalArray, brick_sort, brick_sort_parallel,
heapsort, matrix_multiply_parallel, counting_sort, bucket_sort, cocktail_shaker_sort, quick_sort, longest_common_subsequence)
heapsort, matrix_multiply_parallel, counting_sort, bucket_sort, cocktail_shaker_sort, quick_sort, longest_common_subsequence, longest_increasing_subsequence)


from pydatastructs.utils.raises_util import raises
Expand Down Expand Up @@ -102,7 +102,7 @@ def test_matrix_multiply_parallel():
output = matrix_multiply_parallel(I, J, num_threads=1)
assert expected_result == output

def test_longest_common_sequence():
def test_longest_common_subsequence():
ODA = OneDimensionalArray
expected_result = "['A', 'S', 'C', 'I', 'I']"

Expand All @@ -126,3 +126,25 @@ def test_longest_common_sequence():
Z = ODA(int, [])
output = longest_common_subsequence(Y, Z)
assert str(output) == '[]'

def test_longest_increasing_subsequence():
ODA = OneDimensionalArray
expected_result = "5"

str1 = ODA(int, [1, 3, 8, 4, 7, 6, 12])
output = longest_increasing_subsequence(str1)
assert str(output) == expected_result

expected_result = "3"

I = ODA(int, [9, 11, 8, 14, 12])
output = longest_increasing_subsequence(I)
assert str(output) == expected_result

Y = ODA(int, [1, 2, 3, 4, 4, 3, 7, 9])
output = longest_increasing_subsequence(Y)
assert str(output) == "6"

Z = ODA(int, [4, 2, 5, 8, 11])
output = longest_increasing_subsequence(Z)
assert str(output) == "4"
2 changes: 1 addition & 1 deletion pydatastructs/utils/tests/test_code_quality.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def test_trailing_white_spaces():
if line.endswith(" \n") or line.endswith("\t\n") \
or line.endswith(" ") or line.endswith("\t"):
assert False, "%s contains trailing whitespace at %s"\
%(file_path, line)
%(file_path, line)
line = file.readline()
file.close()

Expand Down