web-dev-qa-db-fra.com

Résoudre presqueIncreasingSequence (Codefights)

Étant donné une séquence d'entiers sous forme de tableau, déterminez s'il est possible d'obtenir une séquence strictement croissante en supprimant un seul élément du tableau.

Exemple

Pour la séquence [1, 3, 2, 1], le résultat devrait être:

almostIncreasingSequence(sequence) = false;

Aucun élément de ce tableau ne peut être supprimé pour obtenir une séquence strictement croissante.

Pour la séquence [1, 3, 2], le résultat devrait être:

almostIncreasingSequence(sequence) = true.

Vous pouvez supprimer 3 du tableau pour obtenir la séquence strictement croissante [1, 2]. Alternativement, vous pouvez supprimer 2 pour obtenir la séquence strictement croissante [1, 3].

Mon code:

def almostIncreasingSequence(sequence):
    c= 0
    for i in range(len(sequence)-1):
        if sequence[i]>=sequence[i+1]:
            c +=1
    return c<1

Mais il ne peut pas passer tous les tests.

input: [1, 3, 2]
Output:false
Expected Output:true

Input: [10, 1, 2, 3, 4, 5]
Output: false
Expected Output: true

Input: [0, -2, 5, 6]
Output: false
Expected Output: true

input:  [1, 1]
Output: false
Expected Output: true

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

Input: [1, 2, 3, 4, 99, 5, 6]
Output: false
Expected Output: true
12
R N

Votre algorithme est beaucoup trop simpliste. Vous avez une bonne idée, en vérifiant les paires consécutives d’éléments que l’élément précédent est inférieur à l’élément ultérieur, mais que davantage est nécessaire.

Créez une routine first_bad_pair(sequence) qui vérifie dans la liste que toutes les paires d'éléments sont en ordre. Si tel est le cas, renvoyez la valeur -1. Sinon, renvoyer l'index de l'élément précédent: il s'agira d'une valeur de 0 à n-2. Ensuite, un algorithme qui fonctionnerait consiste à vérifier la liste d'origine. Si cela fonctionne, d'accord, mais si ce n'est pas le cas, supprimez les éléments incriminés précédents ou suivants. Si l'un ou l'autre fonctionne, bien, sinon pas bien.

Je peux penser à d’autres algorithmes, mais celui-ci semble le plus simple. Si vous n'aimez pas les deux ou trois listes temporaires créées en combinant deux tranches de la liste d'origine, l'équivalent peut être effectué avec des comparaisons dans la liste d'origine à l'aide de plusieurs instructions if.

Voici le code Python qui passe tous les tests que vous affichez.

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

Si vous souhaitez éviter ces listes temporaires, voici un autre code qui comporte une routine de vérification de paires plus complexe.

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

Et voici les tests que j'ai utilisés.

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]))
22
Rory Daulton

C'est à moi. J'espère que ceci vous aidera:

def almostIncreasingSequence(sequence):

    #Take out the Edge cases
    if len(sequence) <= 2:
        return True

    #Set up a new function to see if it's increasing sequence
    def IncreasingSequence(test_sequence):
        if len(test_sequence) == 2:
            if test_sequence[0] < test_sequence[1]:
                return True
        else:
            for i in range(0, len(test_sequence)-1):
                if test_sequence[i] >= test_sequence[i+1]:
                    return False
                else:
                    pass
            return True

    for i in range (0, len(sequence) - 1):
        if sequence[i] >= sequence [i+1]:
            #Either remove the current one or the next one
            test_seq1 = sequence[:i] + sequence[i+1:]
            test_seq2 = sequence[:i+1] + sequence[i+2:]
            if IncreasingSequence(test_seq1) == True:
                return True
            Elif IncreasingSequence(test_seq2) == True:
                return True
            else:
                return False
5
sukai

La raison pour laquelle votre modeste algorithme échoue ici (mis à part le '=' manquant en retour), c’est simplement en comptant les éléments supérieurs au suivant et en renvoyant un résultat si ce nombre est supérieur à 1.

L’important est de regarder la liste après en avoir retiré un élément à la fois et de s’assurer que la liste est toujours triée.

Ma tentative est très courte et fonctionne pour tous les scénarios. Il ne respecte pas la contrainte de temps imposée au dernier ensemble de tests caché seul dans l'exercice.

 enter image description here

Comme le suggère le nom du problème, je souhaitais directement comparer la liste à sa version triée et gérer le cas "presque" plus tard - ce qui donne la quasi-augmentation. c'est à dire.:

if sequence==sorted(sequence):
   .
   .

Mais comme le dit le problème:

déterminez s'il est possible d'obtenir une séquence strictement croissante en ne supprimant pas plus d'un élément du tableau (à la fois).

J'ai commencé à visualiser la liste en supprimant un élément à la fois lors de l'itération et à vérifier si le reste de la liste est une version triée de lui-même. Cela m'amène à ceci:

for i in range(len(sequence)):
    temp=sequence.copy()
    del temp[i]
    if temp==sorted(temp):
        .
        .

C'est ici que j'ai compris que si cette condition est vraie pour la liste complète, nous avons ce qu'il faut: une séquence quasi-croissante! J'ai donc complété mon code de cette façon:

def almostIncreasingSequence(sequence):
    t=0
    for i in range(len(sequence)):
        temp=sequence.copy()
        del temp[i]
        if temp==sorted(temp):
            t+=1
    return(True if t>0 else False)

Cette solution échoue toujours sur des listes telles que [1, 1, 1, 2, 3]. Comme l'a noté @ rory-daulton dans ses commentaires, nous devons faire la différence entre un "trié" et un "ordre croissant" dans ce problème. Alors que le test [1, 1, 1, 2, 3] est trié, il est placé sur une séquence croissante telle que demandée dans le problème. Pour gérer cela, voici le code final avec une condition d'une ligne ajoutée pour vérifier les mêmes numéros consécutifs:

def almostIncreasingSequence(sequence):
    t=0
    for i in range(len(sequence)):
        temp=sequence.copy()
        del temp[i]
        if temp==sorted(temp) and not(any(i==j for i,j in Zip(sorted(temp), sorted(temp)[1:]))):
            t+=1
    return t>0

Comme cela ne respecte toujours pas le délai d’exécution du dernier test (la liste doit être très longue), je cherche toujours un moyen d’optimiser cette solution.

4
Ashish Singh

Je travaille toujours sur le mien. C'est écrit comme ça mais je ne peux pas passer les 3 derniers tests cachés.

def almostIncreasingSequence(sequence):

boolMe = 0
checkRep = 0

for x in range(0, len(sequence)-1):

    if sequence[x]>sequence[x+1]:
        boolMe = boolMe + 1
        if (x!=0) & (x!=(len(sequence)-2)):
            if sequence[x-1]>sequence[x+2]:
                boolMe = boolMe + 1
    if sequence.count(sequence[x])>1:
        checkRep = checkRep + 1

    if (boolMe > 1) | (checkRep > 2):    
        return False
return True
1
TImmuh

Avec Python3, j'ai commencé avec quelque chose comme ça ...

def almostIncreasingSequence(sequence):
    for i, x in enumerate(sequence):
        ret = False
        s = sequence[:i]+sequence[i+1:]
        for j, y in enumerate(s[1:]):
            if s[j+1] <= s[j]:
                ret = True
                break
            if ret:
                break
        if not ret:
            return True
    return False

Mais le chronomètre 29 a été maintenu.

Je me suis lancé quand j'ai réalisé que ça marche aussi, mais que le temps est écoulé pour # 29. Je ne sais pas comment accélérer les choses.

def almostIncreasingSequence(sequence):
    for i, x in enumerate(sequence):    
        s = sequence[:i]
        s.extend(sequence[i+1:])
        if s == sorted(set(s)):
            return True
    return False
1
gingerroot

C'était un exercice plutôt cool.

Je l'ai fait comme ça:

def almostIncreasingSequence(list):
  removedIdx = []                   #Indexes that need to be removed

  for idx, item in enumerate(list):
    tmp = []                        #Indexes between current index and 0 that break the increasing order
    for i in range(idx-1, -1, -1):
      if list[idx]<=list[i]:        #Add index to tmp if number breaks order
        tmp.append(i)
    if len(tmp)>1:                  #If more than one of the former numbers breaks order  
      removedIdx.append(idx)        #Add current index to removedIdx
    else:
      if len(tmp)>0:                #If only one of the former numbers breaks order
        removedIdx.append(tmp[0])   #Add it to removedIdx
  return len(set(removedIdx))<=1

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]))
print(almostIncreasingSequence([1, 1, 1, 2, 3]))
1
mTv

Voici ma solution simple

def almostIncreasingSequence(sequence):
    removed_one = False
    prev_maxval = None
    maxval = None
    for s in sequence:
        if not maxval or s > maxval:
            prev_maxval = maxval
            maxval = s
        Elif not prev_maxval or s > prev_maxval:
            if removed_one:
                return False
            removed_one = True
            maxval = s
        else:
            if removed_one:
                return False
            removed_one = True
    return True
0
theannouncer
boolean almostIncreasingSequence(int[] sequence) {
    int length = sequence.length;
    if(length ==1) return true;
    if(length ==2 && sequence[1] > sequence[0]) return true;
    int count = 0;
    int index = 0;
    boolean iter = true;

    while(iter){
        index = checkSequence(sequence,index);
        if(index != -1){
            count++;
            index++;
            if(index >= length-1){
                iter=false;
            }else if(index-1 !=0){
                if(sequence[index-1] <= sequence[index]){
                    iter=false;
                    count++;
                }else if(((sequence[index] <= sequence[index-2])) && ((sequence[index+1] <= sequence[index-1]))){
                    iter=false;
                    count++;                    
                }
            }
        }else{
            iter = false;
        }
    }
    if(count > 1) return false;
    return true;
}

 int checkSequence(int[] sequence, int index){
    for(; index < sequence.length-1; index++){
        if(sequence[index+1] <= sequence[index]){
            return index; 
        }
    }
    return -1;
}
0
Murali Reddy

Cela fonctionne dans la plupart des cas, sauf en cas de problèmes de performances.

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
Siva Karthikeyan

Eh bien, voici aussi ma solution, .__ Je pense que c'est un peu plus propre que les autres solutions proposées ici, donc je vais l'amener ci-dessous.

En fait, il vérifie si un index dans lequel i - ème valeur est supérieure à (i + 1) - ème valeur, s'il trouve un tel index, vérifie si la suppression de l'un de ces deux fait de la liste une séquence croissante.

def almostIncreasingSequence(sequence):

    def is_increasing(lst):
        for idx in range(len(lst)-1):
            if lst[idx] >= lst[idx + 1]:
                return False
        return True

    for idx in range(len(sequence) - 1):
        if sequence[idx] >= sequence[idx + 1]:
            fixable = is_increasing([*sequence[:idx], *sequence[idx+1:]]) or is_increasing([*sequence[:idx+1], *sequence[idx+2:]])
            if not fixable:
                return False

    return True
0
SpiXel

Vous trouverez ci-dessous le code Python3 que j'ai utilisé et qui a bien fonctionné:

def almostIncreasingSequence(sequence):
flag = False

if(len(sequence) < 3):
    return True

if(sequence == sorted(sequence)):
    if(len(sequence)==len(set(sequence))):
        return True

bigFlag = True
for i in range(len(sequence)):
    if(bigFlag and i < len(sequence)-1 and sequence[i] < sequence[i+1]):
        bigFlag = True
        continue
    tempSeq = sequence[:i] + sequence[i+1:]
    if(tempSeq == sorted(tempSeq)):
        if(len(tempSeq)==len(set(tempSeq))):
            flag = True
            break
    bigFlag = False
return flag
0
Partha S Satpathy