Je travaille sur quelques défis Javascript sur Code Signal et suis tombé sur cette question:
É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 ne supprimant pas plus d'un élément du tableau. **
Remarque: la séquence a0, a1, ..., an est considérée comme strictement croissante si a0 <a1 <... <an. Une séquence contenant un seul élément est également considérée comme strictement croissante.
Exemple Pour sequence = [1, 3, 2, 1], la sortie doit être presqueIncreasingSequence (sequence) = false.
Il n'y a pas un élément dans ce tableau qui puisse être supprimé pour obtenir une séquence strictement croissante. Pour sequence = [1, 3, 2], la sortie doit être presqueIncreasingSequence (sequence) = true.
Vous pouvez supprimer 3 du tableau pour obtenir la séquence strictement croissante [1, 2]. Vous pouvez également supprimer 2 pour obtenir la séquence strictement croissante [1, 3].
Mon approche consiste à parcourir le tableau de séquences, à vérifier si l'élément actuel est supérieur à l'élément suivant, le cas échéant, à supprimer l'élément actuel. Ensuite, incrémentez un compteur, si le compteur est inférieur à 2, retournez true, sinon retournez false.
Voici mon code:
function almostIncreasingSequence(sequence) { // If array has 1 or 2 elements it passes if(sequence.length <= 2) { return true; } // Keeps track of numbers removed let numberRemoved = 0; // Iterate through array, check if current element is greater than next element // If so, increment numberRemoved and remove current element for(let i = 0; i < sequence.length; i++) { if(sequence[i] >= sequence[i + 1]) { numberRemoved++; // Removed element if it's greater than next element let removed = sequence.splice([i], 1); i = 0; console.log(sequence); } } // Second pass through the array checks if there are 2 or more out of order // elements. Inefficient and sloppy, need to find a better approach for(let j = 0; j < sequence.length; j++) { if(sequence[j] >= sequence[j + 1]) { numberRemoved++; } } // If number is less than 2, the sequence passes if(numberRemoved < 2) { return true; } else { return false; } }
Cette solution résout 17/19 cas de test. Je rencontre un cas de pointe où parfois, si i> = [i + 1], la bonne approche serait de supprimer [i + 1] , pas i . Par exemple:
Comment puis-je gérer ce cas de bord? Dans certains cas, si la séquence [i]> = [i + 1], vous devez supprimer la séquence [i] , dans d'autres cas, vous devez supprimer [i + 1] . Comment puis-je résoudre ce problème sans utiliser une seconde boucle for et passer une seconde fois dans le tableau?
6 Réponses :
La question est principalement "devons-nous supprimer un élément ou moins pour obtenir une séquence croissante?". Vous n'avez donc pas besoin de supprimer quoi que ce soit, comptez simplement le nombre d'éléments à supprimer.
De plus, vous devez continuer la vérification sans que la numérotation hors séquence n'échoue aux vérifications suivantes. Dans ce cas, attribuez à prev
le nombre le plus bas entre le courant et le prev
.
function almostIncreasingSequence(sequence) { let removed = 0; let i = 0; let prev = -Infinity; // as long as removed less than 2 times, and i is under arrays length while(removed < 2 && i < sequence.length) { if(sequence[i] > prev) { // if current is bigger the previous prev = sequence[i]; // assign current to previous } else { prev = Math.min(prev, sequence[i]); // take the lowest removed++; // increment removed } i++; } return removed < 2; // true if removed are under 2 } console.log(almostIncreasingSequence([1, 3, 2, 1])); // false console.log(almostIncreasingSequence([1, 3, 2])); // true console.log(almostIncreasingSequence([3, 5, 67, 98, 3])); // true console.log(almostIncreasingSequence([4, 3, 5, 67, 98, 3])); // false console.log(almostIncreasingSequence([1, 4, 2, 3])); // true
Je ne suis pas sûr de bien comprendre la question, mais je pense que celle-ci pourrait être votre réponse ...
function testSequence(arraySequence) { let prev = -Infinity , ret = true , out = false ; for(let val of arraySequence) { if (val<=prev) { if (out) { ret=false; break } else { out=true } } prev=val } return ret } console.log(testSequence([1, 3, 2, 1])); // false console.log(testSequence([1, 3, 2])); // true console.log(testSequence([3, 5, 67, 98, 3])); // true console.log(testSequence([4, 3, 5, 67, 98, 3])); // false
Chaque fois qu'un nombre décroissant est trouvé, nous devons déterminer lequel des 2 nombres consécutifs doit être supprimé. Cela peut être soit:
Si aucun d'eux ne peut corriger la diminution, le tableau n'est déjà pas une "séquence presque croissante", car cela signifie qu'au moins une autre suppression est nécessaire.
function almostIncreasingSequence(sequence) { let removed = 0; let i = 0; let prev = -Infinity; // as long as removed less than 2 times, and i is under arrays length while(removed < 2 && i < sequence.length) { if(sequence[i] > prev) { // if current is bigger the previous prev = sequence[i]; // assign current to previous // remove the latter number, if it fixes the decrease } else if (i === sequence.length - 1 || sequence[i+1] > sequence[i-1]) { removed++; // increment removed } else if (i < 2 || sequence[i] > sequence[i-2]) { // remove the former number, if it fixes the decrease removed++; prev = sequence[i]; } else { // neither option fixes the decrease, so at least 2 removal is needed return false; } i++; } return removed < 2; // true if removed are under 2 } console.log(almostIncreasingSequence([1, 3, 2, 1])); // false console.log(almostIncreasingSequence([1, 3, 2])); // true console.log(almostIncreasingSequence([3, 5, 67, 98, 3])); // true console.log(almostIncreasingSequence([4, 3, 5, 67, 98, 3])); // false console.log(almostIncreasingSequence([1, 4, 2, 3])); // true console.log(almostIncreasingSequence([10, 13, 2, 9])); // false
Bonne prise. J'ai supprimé la partie "Cela échouerait" de votre réponse, car elle a été corrigée. La prochaine fois, un commentaire sur ma réponse, détaillant le problème, serait bien.
Merci pour la mise à jour. J'ai pensé qu'un commentaire serait aussi plus approprié, mais mon compte ne peut pas encore ajouter de commentaires.
Vous pourriez prendre un index trouvé.
Cette approche teste soit trois éléments consécutifs, comme
.as-console-wrapper { max-height: 100% !important; top: 0; }ou prend pour la boucle suivante une vérification qui omet la valeur trouvée en vérifiant l'index trouvé.
function inSequence(array) { var i, found; for (i = 1; i < array.length - 1; i++) { if ((found === i - 1 || array[i - 1] < array[i]) && array[i] < array[i + 1]) continue; if (array[i - 1] >= array[i + 1] || found !== undefined) return false; found = i; } return true; } console.log(inSequence([2, 1])); console.log(inSequence([1, 2, 3])); console.log(inSequence([2, 1, 3])); console.log(inSequence([1, 2, 4, 3])); console.log(inSequence([1, 2, 3, 8, 4, 5, 6, 7])); console.log(inSequence([1, 2, 3, 8, 4, 5, 6, 9, 7])); console.log(inSequence([2, 1, 3, 4, 5, 2])); console.log(inSequence([1, 2, 3, 1, 2, 5, 6, 7])); console.log(inSequence([1, 2, 3, 8, 2, 5, 6, 7]));Ensuite, sinon dans l'ordre, les éléments adjacents sont vérifiés pour éviter ce modèle
v 1 2 3 1 2 5 6 7 3 > 2 v 1 2 3 8 2 5 6 7 3 > 2et s'il est trouvé, plus d'un élément est en mauvaise position.
v 1 2 3 [8 4 5] 6 7 ^ omit value on found index
v 1 2 [3 8 4] 5 6 7 -> found at index 3
La question demande que vous trouviez si, lorsqu'un index dans un tableau est supprimé, le tableau serait une séquence croissante. Par conséquent, si nous ignorons un index qui désobéit à la règle
a i <a i + 1
alors l'autre index doit obéir à la règle.
function almostIncreasingSequence(sequence) { let unorderedIndex = 0; for(let i = 1; i < sequence.length; i++ ){ if( sequence[i-1] >= sequence[i] ) { unorderedIndex++; // an array that's almost increasing would just have one unordered index if( unorderedIndex > 1 ) return false; if( sequence[i-2] >= sequence[i] && sequence[i-1] >= sequence[i+1]) return false; } } return true; }
Voici une solution simple.
function almostIncreasingSequence(sequence) { // initialize removedCount to 0. let removedCount = 0; // iterate through sequence for(let i=0; i<sequence.length-1; i++) { // if current value is greater than the next value ex. [3, 1, 2]; 3 > 1 if(sequence[i] > sequence[i+1]) { // increase count removedCount++; } } // if our count is more than 2 return false, otherwise return true return removedCount <= 1; }
Vérifiez si
[i+1] < [i-1]
. Si c'est le cas, supprimez[i+1]
au lieu de[i]
.