Congrats on a deceptively hard question. I think this will work but I will not be shocked if I missed a corner case, especially with repeated elements. Revised version inspired by Hgu Nguyen's recursive solution:
def sublist(a, b):
index_a = 0
index_b = 0
len_a = len(a)
len_b = len(b)
while index_a < len_a and index_b < len_b:
if a[index_a] == b[index_b]:
index_a += 1
index_b += 1
else:
index_b += 1
return index_a == len_a
Some rough profiling:
Given lists that require traversing most or all of b
, my algorithm suffers:
a = [1, 3, 999999]
b = list(range(1000000))
On my PC, Huu Nguyen or Hetman's algorithm takes about 10 seconds to run 100 iterations of the check. My algorithm takes 20 seconds.
Given an earlier success, Huu's algorithm falls vastly behind:
a = [1, 3, 5]
Hetman's algorithm or mine can complete 100k checks in under a second - Hetman's in 0.13 seconds on my PC, mine in 0.19 seconds. Huu's takes 16 seconds to complete 1k checks. I am frankly astounded at that degree of difference - recursion can be slow if not compiler optimized, I know, but 4 orders of magnitude is worse than I would have expected.
Given a failure list a
, the performance heads back towards what I saw when requiring traversal of the whole second list - understandable, since there's no way to know that there won't be a sequence at the end that matches the otherwise unmatchable list.
a = [3, 1, 5]
Again, about 10 seconds for Huu Nguyen or Hetman's algorithm for 100 tests, 20 for mine.
Longer ordered lists maintain the pattern I saw for early success. EG:
a = range(0, 1000, 20)
With Hetman's algorithm that took 10.99 seconds to complete 100k tests, while mine took 24.08. Huu's took 28.88 to complete 100 tests.
These are admittedly not the full range of tests you could run, but in all cases Hetman's algorithm performed the best.