简体   繁体   English

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

[英]Creating a strictly increasing sequence minus 1 element

I am working through a code challenge where I am to check if a list is strictly increasing if I remove no more than 1 element from the list.我正在处理一个代码挑战,如果我从列表中删除不超过 1 个元素,我将检查列表是否严格增加。 Here are some input/output examples:以下是一些输入/输出示例:

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, 3, 2], the output should be
almostIncreasingSequence(sequence) = true.

This is the logic I've built.这是我建立的逻辑。 Basically, I've created a copy of list and I'm doing the testing on the copy.基本上,我已经创建了一个列表副本,并且正在对副本进行测试。 I remove one element in each iteration and if it is strictly increasing, I increment the counter by a value of 1 but if it isn't, I decrement it by one.我在每次迭代中删除一个元素,如果它严格增加,我将计数器增加 1,但如果不是,我将其减少 1。 At the end, I check if the counter is greater than or equal to 0 and return a boolean value based on that:最后,我检查计数器是否大于或等于 0,并基于此返回 boolean 值:

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

However, there are 2 issues with this code.但是,此代码存在 2 个问题。 First of all, the logic does not work on some test cases like this one:首先,逻辑不适用于像这样的一些测试用例:

Input: sequence: [1, 3, 2]
Output: false
Expected Output: true

And the other issue is that the code takes too long for larger sequences.另一个问题是代码对于更大的序列来说花费的时间太长。 How can I fix my existing code to make it faster and generic for every kind of input?如何修复现有代码以使其对每种输入都更快、更通用? While I appreciate all help, just posting an answer does not help me at all since this is a code challenge meant for learning.尽管我感谢所有帮助,但仅发布答案对我毫无帮助,因为这是一个旨在学习的代码挑战。 Telling me how to optimize my code helps far more than just an answer.告诉我如何优化我的代码不仅仅是一个答案。

From the start, find the strictly increasing prefix.从一开始,找到严格递增的前缀。 From the end find the strictly increasing suffix (strictly decreasing from the end).从末尾找到严格递增的后缀(从末尾严格递减)。

If they overlap, return true because the whole sequence is strictly increasing.如果它们重叠,则返回 true,因为整个序列是严格递增的。

If there are any elements between them, then return false.如果它们之间有任何元素,则返回false。

Otherwise, the prefix and suffix are adjacent.否则,前缀和后缀是相邻的。 Return true if you can connect them into an increasing sequence by deleting the last element in the prefix, or the first element in the suffix.如果您可以通过删除前缀中的最后一个元素或后缀中的第一个元素将它们连接成递增序列,则返回 true。

Try to reduce the number of times you perform an operation that requires you to iterate over the array.尝试减少执行需要遍历数组的操作的次数。 Here's one way where you only need one loop through the array.这是一种只需要一个循环遍历数组的方法。

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

Explanation:解释:

  1. isStrictlyIncreasing() checks that a sequence is strictly increasing. isStrictlyIncreasing() 检查序列是否严格递增。 Pretty self explanatory很不言自明

  2. almostIncreasingSequence() makes two copies of the sequence.几乎IncreasingSequence() 制作序列的两个副本。

    1. When it finds that the sequence is not increasing, it removes both the offending elements, one from each copy.当它发现序列没有增加时,它会删除两个有问题的元素,每个副本一个。
    2. If either of these modified lists is strictly increasing, the original is almost strictly increasing.如果这些修改列表中的任何一个严格递增,则原始列表几乎严格递增。 Otherwise it isn't.否则不是。
    3. If we reach the end of the function, we never found a non-increasing pair, so the list is strictly increasing, so return True .如果我们到达 function 的末尾,我们从来没有找到一个不增加的对,所以列表是严格增加的,所以返回True

To solve this problem in linear time we have to first pre-process the given array.为了linear time解决这个问题,我们必须首先预处理给定的数组。

Suppose the array is [1,2,3,4,5,2,6,7] , now we will make two additional arrays.假设数组是[1,2,3,4,5,2,6,7] ,现在我们将制作两个额外的 arrays。
increasingPrefix which will be a boolean array, in this array i-th element is True iff the prefix till i is an strictly increasing sequence. increasingPrefix前缀,它将是一个 boolean 数组,在这个数组i-th元素为True ,如果prefix till i是严格递增的序列。
Similarly, we will make another array increasingSuffix which will also be a boolean array, here i-th element is True iff suffix till i is a strictly increasing sequence.同样,我们将创建另一个数组increasingSuffix ,它也将是一个boolean数组,这里i-th元素是True ,如果suffix till i是严格递增的序列。

So所以

array = [1, 2, 3, 4, 5, 2, 6, 7]

increasingPrefix = [True, True, True, True, True, False, False, False]

increasingSuffix = [False, False, False, False, False, True, True, True]

Now to check if the given array can become strictly increasing by removing no more than 1 element,现在检查给定数组是否可以通过删除不超过 1 个元素来严格增加,
we can simply traverse the given array and for each i-th element we will check if我们可以简单地遍历给定的数组,对于每个i-th元素,我们将检查是否
increasingPrefix[i-1]==True and increasingSuffix[i+1]==True and array[i+1]>array[i-1] . increasingPrefix[i-1]==True and increasingSuffix[i+1]==True and array[i+1]>array[i-1]
If above condition holds True in any i-th element than ans is True because we can remove i-th element and the remaining array will be strictly increasing.如果上述条件在任何i-th元素中为真,则 ans 为True ,因为我们可以删除i-th元素,剩余的数组将严格增加。

Code for the above idea上述想法的代码

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,-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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM