I was going through common child problem on hackerrank. It is exactly same as a famous Longest Common Subsequence problem.
Using basic concept from CLRS, I implemented first solution. But exceeds time limit on some test cases:
def lcs1(s1, s2):
LCS_table = [[0 for _ in range(len(s2)+1)] # s2 corresponds to columns
for _ in range(len(s1)+1) # s1 corresponds to rows
]
for i in range(1,len(s1)+1):
for j in range(1,len(s2)+1):
if s1[i-1] == s2[j-1]:
LCS_table[i][j] = LCS_table[i-1][j-1] + 1
else:
LCS_table[i][j] = LCS_table[i-1][j] if LCS_table[i-1][j] > LCS_table[i][j-1] else LCS_table[i][j-1]
return LCS_table[-1][-1]
So I went through the leaderboard of hackerrank and come up with second solution which passes all testcases:
def lcs2(s1,s2):
prev = cur = [0] * (len(s2)+1)
for i in range(1, len(s1)+1):
for j in range(1, len(s2)+1):
if s1[i-1] == s2[j-1]:
cur[j] = prev[j-1]+1
else:
cur[j] = prev[j] if prev[j] > cur[j-1] else cur[j-1]
prev, cur = cur, [0] * (len(s2)+1)
return prev[-1]
Q1. Is it because indexing 2D array in lcs1
is costlier than indexing 1D array in lcs2
?
I also referred this solution:
def lcs3(s1, s2):
L = [0] * len(s2)
for c in s1:
p = 0
L = [
p := (q+1 if c==d else r if p < r else p)
for d, q, r in zip(s2, [0]+L, L)
]
return L[-1]
I chosen two random strings and tried these methods on them:
s1='onfjkvbibisbwbriuiwbviwovwwwwmpomqqsbambviubivbsvbwb'
s2='ieubrvbwoqpvponvnxvknoibolkncnsnbvrobrobwvkskdvksvorbqppqwqwqzcx'
print(lcs1(s1,s2)) # 18
print(lcs2(s1,s2)) # 19
print(lcs3(s1,s2)) # 18
Q2. Surprisingly the output of lcs2
differs from that of lcs1
and lcs3
. Where did I make mistake in lcs2? Still how it got accepted in hackerrank? Lack of good test cases?