Solve almostIncreasingSequence (Codefights)

后端 未结 15 1191
谎友^
谎友^ 2020-12-08 07:35

Given a sequence of integers as an array, determine whether it is possible to obtain a strictly increasing sequence by removing no more than one element from the array.

相关标签:
15条回答
  • 2020-12-08 08:20

    This works on most cases except has problems with performance.

    def almostIncreasingSequence(sequence):
        if len(sequence)==2:
            return sequence==sorted(list(sequence))
        else:
            for i in range(0,len(sequence)):
                newsequence=sequence[:i]+sequence[i+1:]
                if (newsequence==sorted(list(newsequence))) and len(newsequence)==len(set(newsequence)):
                    return True
                    break
                else:
                    result=False
        return result
    
    0 讨论(0)
  • 2020-12-08 08:23

    There are two possibilities whenever you hit the condition of the sequence[i-1]>=sequence[i]

    • Delete index i-1
    • Delete index i

    So my idea was to create copy and delete the indexes and check if they are sorted and then at the end you can do the or and return if the ans is attainable. Complexity will be O(N2)[because of del] and space O(N)

    def almostIncreasingSequence(sequence):
        c0,c1=1,1
        n=len(sequence)
        l1=[]
        l2=[]
        for i in sequence:
            l1.append(i)
            l2.append(i)
        for i in range(1,n):
            if sequence[i-1]>=sequence[i]:
                del l1[i]
                del l2[i-1]
                break
        for i in range(1,n-1):
            if l1[i-1]>=l1[i]:
                c0=0
                break
        for i in range(1,n-1):
            if l2[i-1]>=l2[i]:
                c1=0
                break
        return bool(c0 or c1)
    

    This is accepted solution.

    0 讨论(0)
  • 2020-12-08 08:25

    Your algorithm is much too simplistic. You have a right idea, checking consecutive pairs of elements that the earlier element is less than the later element, but more is required.

    Make a routine first_bad_pair(sequence) that checks the list that all pairs of elements are in order. If so, return the value -1. Otherwise, return the index of the earlier element: this will be a value from 0 to n-2. Then one algorithm that would work is to check the original list. If it works, fine, but if not try deleting the earlier or later offending elements. If either of those work, fine, otherwise not fine.

    I can think of other algorithms but this one seems the most straightforward. If you do not like the up-to-two temporary lists that are made by combining two slices of the original list, the equivalent could be done with comparisons in the original list using more if statements.

    Here is Python code that passes all the tests you show.

    def first_bad_pair(sequence):
        """Return the first index of a pair of elements where the earlier
        element is not less than the later elements. If no such pair
        exists, return -1."""
        for i in range(len(sequence)-1):
            if sequence[i] >= sequence[i+1]:
                return i
        return -1
    
    def almostIncreasingSequence(sequence):
        """Return whether it is possible to obtain a strictly increasing
        sequence by removing no more than one element from the array."""
        j = first_bad_pair(sequence)
        if j == -1:
            return True  # List is increasing
        if first_bad_pair(sequence[j-1:j] + sequence[j+1:]) == -1:
            return True  # Deleting earlier element makes increasing
        if first_bad_pair(sequence[j:j+1] + sequence[j+2:]) == -1:
            return True  # Deleting later element makes increasing
        return False  # Deleting either does not make increasing
    

    If you do want to avoid those temporary lists, here is other code that has a more complicated pair-checking routine.

    def first_bad_pair(sequence, k):
        """Return the first index of a pair of elements in sequence[]
        for indices k-1, k+1, k+2, k+3, ... where the earlier element is
        not less than the later element. If no such pair exists, return -1."""
        if 0 < k < len(sequence) - 1:
            if sequence[k-1] >= sequence[k+1]:
                return k-1
        for i in range(k+1, len(sequence)-1):
            if sequence[i] >= sequence[i+1]:
                return i
        return -1
    
    def almostIncreasingSequence(sequence):
        """Return whether it is possible to obtain a strictly increasing
        sequence by removing no more than one element from the array."""
        j = first_bad_pair(sequence, -1)
        if j == -1:
            return True  # List is increasing
        if first_bad_pair(sequence, j) == -1:
            return True  # Deleting earlier element makes increasing
        if first_bad_pair(sequence, j+1) == -1:
            return True  # Deleting later element makes increasing
        return False  # Deleting either does not make increasing
    

    And here are the tests I used.

    print('\nThese should be True.')
    print(almostIncreasingSequence([]))
    print(almostIncreasingSequence([1]))
    print(almostIncreasingSequence([1, 2]))
    print(almostIncreasingSequence([1, 2, 3]))
    print(almostIncreasingSequence([1, 3, 2]))
    print(almostIncreasingSequence([10, 1, 2, 3, 4, 5]))
    print(almostIncreasingSequence([0, -2, 5, 6]))
    print(almostIncreasingSequence([1, 1]))
    print(almostIncreasingSequence([1, 2, 3, 4, 3, 6]))
    print(almostIncreasingSequence([1, 2, 3, 4, 99, 5, 6]))
    print(almostIncreasingSequence([1, 2, 2, 3]))
    
    print('\nThese should be False.')
    print(almostIncreasingSequence([1, 3, 2, 1]))
    print(almostIncreasingSequence([3, 2, 1]))
    print(almostIncreasingSequence([1, 1, 1]))
    
    0 讨论(0)
提交回复
热议问题