我正在尝试查找列表中增长最长的连续子序列。
示例:如果我有一个列表:[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)
答案 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)
。
从数组的开头迭代。
检查下一个元素是否大于当前元素。如果是,则递增数组的结束位置。然后检查这个长度是否比迄今为止遇到的所有时间最大长度都要好。如果是,则分别使用当前的开始和结束初始化beststart
和bestend
。
如果下一个元素不大于当前元素,则重新初始化开始和结束位置。
以下是上述算法的简单实现:
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]