连续增加的后续序列

时间:2016-11-08 04:51:58

标签: python arrays list

我正在尝试查找列表中增长最长的连续子序列。

示例:如果我有一个列表:[1,2,3,0,2,3,5,6,7,1,4,5,6,9],则输出应为[0,2,3,5,6,7],因为它长于[1,2,3][1,4,5,6,9]

我编写了我的代码,我可以将列表分成较小的列表(如上所示),但只计算每个较小序列的长度。但我需要做的是输出最长的子序列而不是它的长度,因为一些奇怪的原因我似乎无法做到这一点(我不断得到逻辑错误)。

所以这是我的代码,这是我尝试实现它的一种方式,我面临的问题是将temp追加到arr2时。请帮我解决这个问题并建议我可以使用另一种更有效的算法吗?

arr = [1,2,3,0,2,3,5,6,7,1,4,5,6,9] #original list 
arr2 = [] #empty list (2 dimension)
counter  = 1 

temp = [] #temporary list
for x,y in enumerate(arr):

    if(x == 0):
        temp.append(y) #append first value to temp
    else:

        if(arr[x] > arr[x-1]): #if value of x is greater than previous one:

            counter += 1 #increase counter if condition met
            temp.append(y) #append list value to temp

        else: #if value of x is not greater than previous one:

            print(temp)
            arr2.append(temp) #append entire temp list to arr2
            temp[:] = [] #clear the temp list
            temp.append(y) #append the new lowest value to temp
            counter = 1 #reset counter

print(arr2)

5 个答案:

答案 0 :(得分:2)

首先,您在撰写时复制对列表的引用:
arr2.append(temp)
然后,您更新列表temp,这样您最终会在arr2中找到对同一列表的多个引用。 你应该复制一份清单:
arr2.append(temp[:])

此外,您永远不会复制找到的最后一个子序列,因此您在arr2中遗漏了一个子序列。 您可以在for循环之外执行此操作,例如:

        else: #if value of x is not greater than previous one:

            print(temp)
            arr2.append(temp) #append entire temp list to arr2
            temp[:] = [] #clear the temp list
            temp.append(y) #append the new lowest value to temp
            counter = 1 #reset counter

arr2.append(temp[:])
print(arr2)

有了上述内容,当您打印[[1, 2, 3], [0, 2, 3, 5, 6, 7], [1, 4, 5, 6, 9]]时,您将获得arr2。 然后,只需选择里面最长的列表。

答案 1 :(得分:1)

首先让l0成为给定列表:

l0 = [1,2,3,0,2,3,5,6,7,1,4,5,6,9]

接下来,我们创建一个l0的所有连续子列表的列表,但是我们抛出那些不增加的子列表(参见结束生成器对象的if语句)。

l1 = [l0[i:j] for i in xrange(len(l0)-1) for j in xrange(i,len(l0)) if l0[i:j] == sorted(l0[i:j])] ## all substrings of l0 that are increasing.  

你要求的是最长的子串。所以只返回那些长度的最大值:

print max([len(l) for l in l1])

答案 2 :(得分:1)

这是解决上述问题的最有效算法。它的时间复杂度为O(N),空间复杂度为O(1)

  • 从数组的开头迭代。

  • 检查下一个元素是否大于当前元素。如果是,则递增数组的结束位置。然后检查这个长度是否比迄今为止遇到的所有时间最大长度都要好。如果是,则分别使用当前的开始和结束初始化beststartbestend

  • 如果下一个元素不大于当前元素,则重新初始化开始和结束位置。

以下是上述算法的简单实现:

arr = [1,2,3,0,2,3,5,6,7,1,4,5,6,9] #original list 

l = len(arr)  # l stores the length of the array
i = 0  # initialize i, iterate from left of the array

max = 1  # the max is always a one element array

start = 0  # initialize start at the beginning of the array
end = 0  # initialize end at the beginning of the array

beststart = 0  # initialize beststart at the beginning of the array
bestend = 0  # initialize bestend at the beginning of the array

while i<l:
    if i+1 < l and arr[i+1]>arr[i]:
        end = end + 1  # increment end, as we found a longer array
        if (end-start+1) > max:
            max = (end - start + 1)  # update max
            beststart = start  # update beststart as we have the longest array till this point
            bestend = end  # update bestend as we have the longest array till this point
    else:
        start = i+1  # re-initialize start
        end = i+1  # re-initialize end

    i = i + 1

print (arr[beststart:bestend+1])  # print the longest array

输出[0, 2, 3, 5, 6, 7]

答案 3 :(得分:0)

无需创建新列表的解决方案。

def max_inc_seq(seq):
    first_ret = first_curr = 0
    last_ret = last_curr = 0
    for i in range(1, len(seq)):
        if seq[i] > seq[i-1]:
            last_curr = i  # move pointer to the item
        else:
            last_curr = first_curr = i  # reset pointers
        len_curr = last_curr - first_curr 
        len_ret = last_ret - first_ret
        if len_curr > len_ret:  # the current seq. longer what longest for now
            first_ret = first_curr
            last_ret = last_curr            
    return seq[first_ret:last_ret+1]

max_inc_seq的测试:

seqs = (
    ([0, 1, 2], [0, 1, 2]),
    ([1,2,3,0,2,3,5,6,7,1,4,5,6,9], [0, 2, 3, 5, 6, 7]),
    ([1, 0], [1]),
    ([-1, 0, 1], [-1, 0, 1]),
    ([0, 1, 1], [0, 1]),
    )

for seq, test in seqs:
    ret = max_inc_seq(seq)
    assert ret == test, "{} != {}".format(ret, test)

答案 4 :(得分:0)

具有2种指针技术的O(n)解决方案:

def longest_inc_seq(arr):
    s, f = 0, 0
    S, F = 0, 0
    currentMaxLen = 0
    for i in range(len(arr) - 1):
        f += 1
        # if the next element is smaller, reset the slow pointer
        if arr[i] > arr[i+1]:
            s = i + 1
        # update currentMaxLen, S and F if the distance between the pointers 
        # is bigger than the currentMaxLen from the last iteration
        if (f-s) > currentMaxLen:
            S, F = s, f
            currentMaxLen = f-s
    print arr[S:F+1]