4

You are given an array of numbers, say

nums = [2, 5, 3, 3, 4, 6]

And want to get the longest possible sequence of numbers, that are ascending, though not necessarily consequent, while maintaining their order.

So the longest array of numbers where An < An+1. In this case:

[2, 3, 4, 6]

I have done this via recursion and loops, testing every possibility. This however takes way too much time for larger arrays and so my question is, whether there is a better/faster method to do this.

Thanks in advance!

Here's my previous code, which returned the length of the final array

def bestLine(arr):
    maximum = 0
    for i in range(0, len(arr)):
        if (len(arr)-i < maximum):
            break
        maximum = max(maximum, f(i, len(arr), arr))
    return maximum

def f(start, end, arr):
    best = 0
    for i in range(start+1, end):
        if (end-i < best):
            break
        if (arr[i] > arr[start]):
            best = max(best, f(i, end, arr))
    return 1 + best
Tievens
  • 51
  • 4
  • 2
    Here are the search keywords you need: https://www.google.com/search?q=longest+increasing+subsequence – user2357112 Oct 14 '17 at 15:19
  • 1
    If you have done this using recursion, it might be worth posting this. – Willem Van Onsem Oct 14 '17 at 15:21
  • 4
    Possible duplicate of [Longest increasing subsequence](https://stackoverflow.com/questions/3992697/longest-increasing-subsequence) – Sundeep Oct 14 '17 at 15:22
  • for condition **An < An+1** answer is `[3, 4, 6]`, because **n&n+1**, so must be sequence (neighbour), must not skip. `[2, 3, 4, 6]` is answer if **Ax < Ay** , **0<=x – b m gevariya Oct 25 '19 at 04:23

1 Answers1

0

My solution:

def best_sequence_length(arr):
    '''Find length of the longest ascending sequence in an array'''
    arr_length = len(arr)
    if arr_length <= 1:
        return arr_length
    longest = [1] # will store the lengths of the longest sequence ending on this index
    best_idx_at_all = 0
    for idx in range(1, arr_length):
        best_len_so_far = 1
        back = -1
        for i in range(len(longest)+1):
            if arr[i] < arr[idx] and best_len_so_far <= longest[i]:
                best_len_so_far = longest[i] + 1
                back = i
        longest.append(longest[back]+1 if back > -1 else 1)
        if longest[best_idx_at_all] < longest[idx]:
            best_idx_at_all = idx
    return longest[best_idx_at_all]

This is maybe not very "pythonic" (it resembles C or even FORTRAN code :-), but it is of O(n^2) complexity.

If you want to get the longest sequence itself, not just its length (which may be ambiguous), the above function requires just slight modification:

def best_sequence(arr):
    '''Find longest ascending sequence in an array'''
    arr_length = len(arr)
    if arr_length <= 1:
        return arr
    longest = [1] # will store the length of the longest sequence ending on this index
    back_link = [-1] # link to the previous element in the longest sequence or -1
    best_idx_at_all = 0
    for idx in range(1, arr_length):
        best_len_so_far = 1
        back = -1
        for i in range(len(longest)+1):
            if arr[i] < arr[idx] and best_len_so_far <= longest[i]:
                best_len_so_far = longest[i] + 1
                back = i
        back_link.append(back)
        longest.append(longest[back]+1 if back > -1 else 1)
        if longest[best_idx_at_all] < longest[idx]:
            best_idx_at_all = idx

    nxt = best_idx_at_all
    result = []
    while nxt >= 0:
        result.append(arr[nxt])
        nxt = back_link[nxt]

    return list(reversed(result))