É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
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]))
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
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.
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.
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
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
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]))
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
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;
}
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
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
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