如何确定是否有可能获得严格增加的序列?

时间:2017-04-29 23:03:10

标签: python arrays

我需要确定一个函数,该函数对于给定的整数序列(作为数组),并且可以通过从数组中删除不超过一个元素来确定是否可以获得严格增加的序列。

数组可以在范围内

2 ≤ sequence.length ≤ 10^5, -10^5 ≤ sequence[i] ≤ 10^5

例如:

[1, 3, 2, 1]我们不能删除任何一个数字以获得增加的序列,因此该函数应该返回False[0, -2, 5, 6][1, 1][1, 3, 2]

我想编写从列表中删除一个数字的函数,并检查序列是否在增加。如果对于所有迭代,我们变为False,而函数应返回False

def almostIncreasingSequence(sequence):
    def order(A):
        n = len(A)
        for i in range(n):
           if A[i] >= A[i+1]:
              result = True
        else:
              result = False            
    for i in range(len(s0)-1):
        s_i = list(sequence)
        s_i.remove(s_i.index(s_i[i]))
           if order(s_i) == True:
    return True

但我犯了一个错误:

  

ValueError:list.remove(x):x不在列表中

是什么原因?我如何完成我的代码?

2 个答案:

答案 0 :(得分:3)

如评论中所述,您可以使用numpy.diff,因此无需检查从列表中删除1个元素的每个组合

import numpy

def almostIncreasingSequence(sequence):
    diff = numpy.diff(sequence) < 1
    return diff.sum() < 2

首先我们得到相邻元素之间的差异,然后我们询问这些差异小于1的位置并计算它,并根据我们得到答案的数量。

没有numpy,我们可以使用类似的技术

import itertools

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a,b = itertools.tee(iterable)
    next(b,None)
    return zip(a,b) # use itertools.izip in python 2

def almostIncreasingSequence(sequence):
    return sum( a>=b for a,b in pairwise(sequence)) < 2    

并且这个优点是使用比numpy版本更少的内存

这里有一些测试

assert almostIncreasingSequence([0, -2, 5,  6])
assert almostIncreasingSequence([1,1])
assert almostIncreasingSequence([1,3,2])
assert almostIncreasingSequence([1,2,3,0])
assert almostIncreasingSequence([1,2,3,0,10])
assert almostIncreasingSequence([10,1,2,3,4])
assert almostIncreasingSequence([1,10,2,3,4])
assert not almostIncreasingSequence([1,2,3,0,0])
assert not almostIncreasingSequence([1,2,0,3,0,10])
assert not almostIncreasingSequence([1,2,0,3,10,0])
assert not almostIncreasingSequence([1,2,3,0,10,0])
assert not almostIncreasingSequence([10,1,2,3,10,0])
assert not almostIncreasingSequence([1, 3, 2, 1])

回应评论,这是一个早期停止版本

def almostIncreasingSequence(sequence):
    diff = 0
    for a,b in pairwise(sequence):
        if a>=b:
            diff += 1
            if diff >= 2:
                return False
    return diff < 2

和随附的测试

assert not almostIncreasingSequence(itertools.chain([1, 3, 2, 1],range(10**100))) # use xrange with python 2

这将花费其他任何其他版本的年龄

答案 1 :(得分:1)

def almostIncreasingSequence(sequence):
    for i in range(len(sequence)-1):
        s_i = list(sequence)

        # Remove the item by index
        del s_i[i]

        if order(s_i) == True:
            return True

    # Need to return false at the end if we never find a solution
    return False

# You should have tested this function separately first.
# It did not work, so obviously almostIncreasingSequence wouldn't work.
def order(A):
    n = len(A)

    # Should have been n-1, not n, because you compare against n+1
    # which doesn't exist when you hit the tail
    for i in range(n - 1):
        if A[i] > A[i + 1]:
            # Need to actually return the value, not just set it to a variable
            return False
    # Only tell us it's in order if ALL the values don't fail
    return True

print almostIncreasingSequence([1, 3, 2])