【问题标题】:how to determine whether it is possible to obtain a strictly increasing sequence?如何判断是否有可能得到严格递增的序列?
【发布时间】:2017-04-29 23:03:09
【问题描述】:

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

数组可以在范围内

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 不在列表中

是什么原因?我怎样才能完成我的代码?

【问题讨论】:

  • list.remove() 从列表中删除(第一个)元素。你给它的是元素的 index
  • 值得一提的是:numpy 有一个diff 函数。

标签: python arrays


【解决方案1】:

如 cmets 中所述,您可以为此使用 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])

响应cmets,这里是提前停止版本

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

其他任何版本都需要很长时间

【讨论】:

    【解决方案2】:
    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])
    

    【讨论】:

    • AFAICT,这种方法(O(n**2))比其他答案(O(n))慢得多。
    • 正确,但 OP 询问如何修复他的代码,而不是如何最好地完成任务。该问题还表明 OP 对于编码来说相当新,在这个阶段应该优先考虑简单性而不是效率。他们显然只是在学习编程,而不是计算机科学。
    • 我明白你的意思。答案是为社区编写的,而不仅仅是为 OP。下次,您可以考虑添加关于效率的小评论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-30
    相关资源
    最近更新 更多