Discover long patterns

前端 未结 6 1813
逝去的感伤
逝去的感伤 2021-01-30 02:20

Given a sorted list of numbers, I would like to find the longest subsequence where the differences between successive elements are geometrically increasing. So if the list is <

6条回答
  •  一生所求
    2021-01-30 02:52

    I think this task is related with not so long ago posted Longest equally-spaced subsequence. I've just modified my algorithm in Python a little bit:

    from math import sqrt
    
    def add_precalc(precalc, end, (a, k), count, res, N):
        if end + a * k ** res[1]["count"] > N: return
    
        x = end + a * k ** count
        if x > N or x < 0: return
    
        if precalc[x] is None: return
    
        if (a, k) not in precalc[x]:
            precalc[x][(a, k)] = count
    
        return
    
    def factors(n):
        res = []
        for x in range(1, int(sqrt(n)) + 1):
            if n % x == 0:
                y = n / x
                res.append((x, y))
                res.append((y, x))
        return res
    
    def work(input):
        precalc = [None] * (max(input) + 1)
        for x in input: precalc[x] = {}
    
        N = max(input)
    
        res = ((0, 0), {"end":0, "count":0})
        for i, x in enumerate(input):
            for y in input[i::-1]:
                for a, k in factors(x - y):
                    if (a, k) in precalc[x]: continue
                    add_precalc(precalc, x, (a, k), 2, res, N)
    
            for step, count in precalc[x].iteritems():
                count += 1
                if count > res[1]["count"]: res = (step, {"end":x, "count":count})
                add_precalc(precalc, x, step, count, res, N)
            precalc[x] = None
    
        d = [res[1]["end"]]
        for x in range(res[1]["count"] - 1, 0, -1):
            d.append(d[-1] - res[0][0] * res[0][1] ** x)
        d.reverse()
        return d
    

    explanation

    • Traversing the array
    • For each previous element of the array calculate factors of the difference between current and taken previous element and then precalculate next possible element of the sequence and saving it to precalc array
    • So when arriving at element i there're already all possible sequences with element i in the precalc array, so we have to calculate next possible element and save it to precalc.

    Currently there's one place in algorithm that could be slow - factorization of each previous number. I think it could be made faster with two optimizations:

    • more effective factorization algorithm
    • find a way not to see at each element of array, using the fact that array is sorted and there's already a precalculated sequences

提交回复
热议问题