创建一个严格递增的序列减去1个元素

问题描述

我正在解决一个代码挑战,如果我从列表中删除不超过1个元素,我将检查列表是否在严格增加。以下是一些输入/输出示例:

Class MyClass(object):
   def __init__(self,....):
      .....

   self.headers = {"Content-Type": "application/json"}

这是我建立的逻辑。基本上,我已经创建了列表的副本,并且正在对该副本进行测试。我在每次迭代中都删除一个元素,如果严格将其增加,则将计数器的值增加1,但如果不是,则将其减1。最后,我检查计数器是否大于或等于0,并根据该值返回布尔值:

For sequence = [1,3,2,1],the output should be
almostIncreasingSequence(sequence) = false.

There is no one element in this array that can be removed in order to get a strictly increasing sequence.

For sequence = [1,2],the output should be
almostIncreasingSequence(sequence) = true.

但是,此代码有2个问题。首先,该逻辑不适用于某些像这样的测试用例:

def almostIncreasingSequence(sequence):
    
    check = 0
    sequence_copy = sequence
    
    for element in sequence:
        sequence_copy.remove(element)
        
        if all(i < j for i,j in zip(sequence_copy,sequence_copy[1:])):
            check += 1
        else:
            check -= 1
        
        sequence_copy = sequence  
    
    if check > 0:
        return True
    else:
        return False

一个问题是,对于较大的序列,代码花费的时间太长。如何修正现有代码,使其对每种输入都更快,更通用?尽管我感谢所有帮助,但是发布答案对我完全没有帮助,因为这是学习所面临的代码挑战。告诉我如何优化代码不仅可以提供答案,还可以提供更多帮助。

解决方法

从头开始,找到严格增加的前缀。从末尾找到严格增加的后缀(从末尾开始严格减少)。

如果它们重叠,则返回true,因为整个序列严格增加。

如果它们之间有任何元素,则返回false。

否则,前缀和后缀是相邻的。如果可以通过删除前缀中的最后一个元素或后缀中的第一个元素将它们按递增顺序连接起来,则返回true。

,

尝试减少执行需要遍历数组的操作的次数。这是一种只需要遍历数组的循环的一种方法。

def isStrictlyIncreasing(sequence):
    for elem1,elem2 in zip(sequence[:-1],sequence[1:]):
        if elem1 >= elem2:
            return False
    return True

def almostIncreasingSequence(sequence):
    seq_copy1 = sequence[:]
    seq_copy2 = sequence[:]
    for i,(elem1,elem2) in enumerate(zip(sequence[:-1],sequence[1:])):
        if elem1 >= elem2:
            seq_copy1.pop(i)
            seq_copy2.pop(i+1)
            return isStrictlyIncreasing(seq_copy1) or isStrictlyIncreasing(seq_copy2)
    return True

说明:

  1. isStrictlyIncreasing()检查序列是否严格增加。很自我解释

  2. almostIncreasingSequence()复制该序列的两个副本。

    1. 当发现序列没有增加时,它将删除两个有问题的元素,每个副本中一个。
    2. 如果这些修改列表中的任何一个严格增加,则原始列表几乎严格增加。否则不是。
    3. 如果到达函数末尾,则永远不会找到不增加对的对,因此列表严格增加,因此请返回True
,

要在linear time中解决此问题,我们必须先对给定数组进行预处理。

假设数组为[1,2,3,4,5,6,7],现在我们将再创建两个数组。
increasingPrefix将是一个布尔数组,如果i-th是严格递增的序列,则此数组True中的元素为prefix till i
同样,我们将创建另一个数组increasingSuffix,它也是一个布尔数组,这里的i-th元素是True,如果suffix till i是一个严格增加的序列。

所以

array = [1,7]

increasingPrefix = [True,True,False,False]

increasingSuffix = [False,True]

现在要检查是否可以通过删除不超过1个元素来严格增加给定数组,
我们可以简单地遍历给定数组,对于每个i-th元素,我们将检查
increasingPrefix[i-1]==True and increasingSuffix[i+1]==True and array[i+1]>array[i-1]
如果以上条件在任何True元素中拥有i-th,则ans为True,因为我们可以删除i-th元素,并且剩余数组将严格增加。

上述想法的代码

def fun(arr):
    n=len(arr)
    
    # empty and 1 length sequences are strictly increasing
    if n<=1:
        return True
    increasingPrefix=[False]*n
    increasingSuffix=[False]*n
    increasingPrefix[0]=True
    increasingSuffix[n-1]=True

    # Calculate increasingPrefix values as described above
    for i in range(1,n):
        if arr[i]>arr[i-1]:
            increasingPrefix[i]=True
        else:
            for j in range(i,n):
                increasingPrefix[j]=False
            break

    # calculated increasingSuffix values as described above
    for i in range(n-2,-1,-1):
        if arr[i]<arr[i+1]:
            increasingSuffix[i]=True
        else:
            for j in range(i,-1):
                increasingSuffix[j]=False
            break

    # traverse the given array and check for the conditions
    ans=False
    for i in range(n):
        if i==0:
            if increasingSuffix[i+1]:
                ans=True
                break
        elif i==n-1:
            if increasingPrefix[i-1]:
                ans=True
                break
        else:
            if increasingPrefix[i-1] and increasingSuffix[i+1] and arr[i+1]>arr[i-1]:
                ans=True
                break
 return ans