Python 确定输入列表是否严格增加
我试图弄清楚输入列表是否是严格递增的列表。此外,如果从列表中只删除一个元素,结果会出现一个严格增加的列表,我们仍然认为列表是真的。这是我的密码。它似乎有一个索引错误,但我不明白为什么Python 确定输入列表是否严格增加,python,python-3.x,list,Python,Python 3.x,List,我试图弄清楚输入列表是否是严格递增的列表。此外,如果从列表中只删除一个元素,结果会出现一个严格增加的列表,我们仍然认为列表是真的。这是我的密码。它似乎有一个索引错误,但我不明白为什么 def almostIncreasingSequence(sequence): n=len(sequence) count=0 if n<=2: return True for i in range (n-1): #test if the i
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
def几乎递增顺序(顺序):
n=len(序列)
计数=0
如果n=序列[j]:
序列pop(i)
计数+=1
#如果有一个以上的元素需要删除,则为false
如果计数>1:
返回错误
返回真值
如果您使用Python为范围内的i(len(some_list))编写了,
,那么您可能做了错误的事情。这确实是这一计划失败的原因n
是任何处理之前的序列长度,但该长度可以随着列表中的pop
项的变化而变化
更好的方法是比较每个需要删除的索引标记,然后一次将它们全部删除,或者更好的方法是——根本不要删除它们!!这是一个没有很好解释的副作用
您可以通过使用itertools.compositions
构建可能严格增加的所有序列的列表,将每对序列与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)
导入itertools
def成对(可编辑):
(a,b)=itertools.T形三通(ITERRABLE)
下一个(b,无)#前进b
返回拉链(a、b)
def几乎递增顺序(顺序):
如果没有顺序:
返回真值
#如果列表为空
组合=itertools.组合(序列,len(序列)-1)
#combos是缺少一个元素的每个有序组合
#它是作为迭代器处理的,因此如果可以的话,我们不会做额外的工作
#早点离开。
def严格增加(cs):
返回所有(a
def几乎递增顺序(顺序):
如果len(序列)<3:
返回真值
a、 b,*顺序=顺序
跳过=0
对于按顺序排列的c:
如果a
你需要做的唯一一件事就是浏览列表,计算次数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
好的,所以这个问题不是那么容易 如果你想要一个有效的解决方案,我认为你最好的选择可能是一个类似的算法 但在这里,我们并不关心实际的最长递增子序列——我们只需要它的长度。此外,如果我们已经必须执行
n
插入(其中n
是我们对“无序”元素数量的限制),那么在维护有序列表时,我们可能会短路
这也很好地概括了n
元素“几乎增加”的情况,在最坏的情况下,对大小M-n-1
到M
的列表执行n-1
二进制搜索,其中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
我正在尝试删除比后面的元素大的元素。我数了数这件事做了多少次。如果删除了多个项目,则列表不会增加。您是否必须(或应该?)实际删除一个有问题的项目?对
sequence[i]>sequence[i+1]
的i
个数进行单次计数就足够了。你得到了一个索引器,因为你在对列表进行迭代的同时使它变小了,所以对于范围(n-1)中的i:
是无效的。@chepner在测试像[10,1,2,3,4]这样的列表时,如果我不删除第一个元素,结果将是错误的,因为count是4,但是删除10将导致True;我的问题是,sequence
作为一种副作用,是否也要求将sequence设置为单调递增的序列?几乎递增的序列([1,2,3,2,2,2])
返回True
,当它应该是False
时。现在改变了,这个算法应该可以工作了(尽管它的性能要差得多)@JingLi好的,第三次是魅力。@Adam Smith现在可以了。非常感谢。我还有一个问题。如果序列[i]>=sequence[j],停止循环并向count添加一个,然后设置i=i+1,是否可以更改我的原始代码,而不是删除列表中的数字?然后再次启动循环?@AdamSmithValueError:r必须是非负的
如果序列是空列表(OPs代码似乎将任何小于3的序列计数为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
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
>>> 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