我试图弄清楚输入列表是否是一个严格增加的列表。此外,如果从列表中只删除一个元素会导致严格增加的列表,我们仍然认为列表为true。这是我的代码。它似乎有一个索引错误,但我不明白为什么。
def almostIncreasingSequence(sequence):
n=len(sequence)
count=0
if n<=2:
return True
for i in range (n-1):
#test if the i-th element is bigger or equal to the elements after it. If it is, remove that element, and add one to count
for j in range (i+1,n):
if sequence[i]>=sequence[j]:
sequence.pop(i)
count+=1
#if there is more than one element that has to be taken out, it's false
if count>1:
return False
return True
答案 0 :(得分:3)
def almost_increasing_sequence(sequence):
if len(sequence) < 3:
return True
a, b, *sequence = sequence
skipped = 0
for c in sequence:
if a < b < c: # XXX
a, b = b, c
continue
elif b < c: # !XX
a, b = b, c
elif a < c: # X!X
a, b = a, c
skipped += 1
if skipped == 2:
return False
return a < b
if __name__ == '__main__':
assert almost_increasing_sequence([]) is True
assert almost_increasing_sequence([1]) is True
assert almost_increasing_sequence([1, 2]) is True
assert almost_increasing_sequence([1, 2, 3]) is True
assert almost_increasing_sequence([3, 1, 2]) is True
assert almost_increasing_sequence([1, 2, 3, 0, 4, 5, 6]) is True
assert almost_increasing_sequence([1, 2, 3, 0]) is True
assert almost_increasing_sequence([1, 2, 0, 3]) is True
assert almost_increasing_sequence([10, 1, 2, 3, 4, 5]) is True
assert almost_increasing_sequence([1, 2, 10, 3, 4]) is True
assert almost_increasing_sequence([1, 2, 3, 12, 4, 5]) is True
assert almost_increasing_sequence([3, 2, 1]) is False
assert almost_increasing_sequence([1, 2, 0, -1]) is False
assert almost_increasing_sequence([5, 6, 1, 2]) is False
assert almost_increasing_sequence([1, 2, 3, 0, -1]) is False
assert almost_increasing_sequence([10, 11, 12, 2, 3, 4, 5]) is False
答案 1 :(得分:3)
好吧,事实证明这个问题 不容易。
如果你想要一个有效的解决方案,我认为你最好的选择可能是类似于longest increasing subsequence problem的算法。
但是在这里,我们并不关心实际上增长最快的子序列 - 我们只需要它的长度。此外,如果我们必须执行n
插入,我们可以在维护有序列表时短路(其中n
是我们对&#34;无序&#34;元素数量的限制)。
这也很好地概括了n
元素&#34;几乎增加&#34;大多数情况下,在大小为n-1
到M-n-1
的列表上执行M
二进制搜索,其中M
是列表的大小。
import bisect
def almost_increasing(li, n=1):
if len(li) < 2:
return True
ordered_li = [li[0]]
violator_count = 0
for ele in li[1:]:
if ele < ordered_li[0]:
violator_count += 1
ordered_li[0] = ele
elif ele > ordered_li[-1]:
ordered_li.append(ele)
else:
violator_count += 1
insertion_pos = bisect.bisect_right(ordered_li, ele)
ordered_li[insertion_pos] = ele
if violator_count > n: return False
return True
这个算法背后的想法如下:
当我们到达新元素时
如果该元素无法附加到我们的有序子序列上,则它是一个违反者&#34;不断增加的财产。我们随后使用bisect
将其插入正确位置的有序子序列中进行二进制搜索。
否则,我们只是将其附加到我们订购的子序列中并继续。
在每次迭代结束时,如果我们有太多的违规者,我们就可以短路了。否则,在循环完成后,我们保证有一个增加的子序列,其长度在原始列表长度的n
之内。
<强>演示强>
>>> almost_increasing([5, 1, 2, 3, 4])
True
>>> almost_increasing([1, 2, 5, 2, 15, 0, 176])
False
>>> almost_increasing([1, 2, 5, 2, 15, 0, 176], 2)
True
答案 2 :(得分:2)
如果您在Python中编写for i in range(len(some_list))
,那么您可能做错了。这确实是失败的原因。 n
是在任何处理之前的序列的长度,但该长度可以随着列表中的pop
项而改变。
更好的方法是比较每个标记需要删除的标记,并一次完成所有这些标记,或者更好的方法 - 根本不删除它们!这是一个没有得到很好解释的副作用。
您可以通过使用itertools.combinations
构建可能严格增加的所有序列的列表,将每对与itertools
pairwise
配方进行比较,然后缩短只要至少有一个就是电路。
import itertools
def pairwise(iterable):
(a, b) = itertools.tee(iterable)
next(b, None) # advance b
return zip(a, b)
def almostIncreasingSequence(sequence):
if not sequence:
return True
# in case of empty list
combos = itertools.combinations(sequence, len(sequence)-1)
# combos is each ordered combination that's missing one element
# it is processed as an iterator, so will do no extra work if we can
# exit early.
def strictly_increasing(cs):
return all(a < b for (a, b) in pairwise(cs))
return any(strictly_increasing(c) for c in combos)
答案 3 :(得分:-1)
您唯一需要做的就是遍历列表,计算sequence[i] > sequence[i+1]
的次数。如果它最多发生一次,那么你的列表几乎会单调增加。
def almostIncreasingSequence(sequence):
count = 0
for i in range(0, len(sequence) - 1):
if sequence[i] > sequence[i+1]:
count += 1
return count < 2
您也可以避免计数,因为例外的数量很少。一旦找到第二个异常,只需返回False
,由初始化为True
的布尔变量的值跟踪。
def almostIncreasingSequence(sequence):
increasing = True
for i in range(0, len(sequence) - 1):
if sequence[i] > sequence[i+1]:
if increasing:
increasing = False
else:
return False
return True