J'ai écrit une fonction javascript pour analyser la plus grosse baisse d'un tableau. Mais un petit problème est toujours là. En tant que valeur maximale, j'obtiens toujours la valeur maximale de ma matrice de trous et non de ma chute.
Exemple: Tableau: [100,90,80,120]
La plus grande chute serait entre 100 et 80. Donc max doit être 100 et minimum 80. Ma fonction renvoie toujours la valeur la plus élevée de tout le tableau. dans mon cas 120
function checkData(data) {
let max = 0
let min = 0
let drop = 0
for (let i = 0; i < data.length; i++) {
if (max < data[i]) {
max = data[i] //?
} else {
let tempDrop = max - data[i]
drop = Math.max(tempDrop, drop)
min = max - drop
}
}
return [max, min, drop]
}
Je veux obtenir le plus grand delta chronologique correct de gauche à droite
Votre boucle doit garder une trace de la chute actuelle et la comparer à la plus grosse chute précédente. Vous pouvez le faire en suivant les index:
function checkData(data) {
let bestDropStart = 0
let bestDropEnd = 0
let bestDrop = 0
let currentDropStart = 0
let currentDropEnd = 0
let currentDrop = 0
for (let i = 1; i < data.length; i++) {
if (data[i] < data[i - 1]) {
// we are dropping
currentDropEnd = i
currentDrop = data[currentDropStart] - data[i]
} else {
// the current drop ended; check if it's better
if (currentDrop > bestDrop) {
bestDrop = currentDrop
bestDropStart = currentDropStart
bestDropEnd = currentDropEnd
}
// start a new drop
currentDropStart = currentDropEnd = i
currentDrop = 0
}
}
// check for a best drop at end of data
if (currentDrop > bestDrop) {
bestDrop = currentDrop
bestDropStart = currentDropStart
bestDropEnd = currentDropEnd
}
// return the best drop data
return [data[bestDropStart], data[bestDropEnd], bestDrop]
}
console.log(checkData([100, 90, 80, 120]))
console.log(checkData([100, 90, 80, 120, 30]))
console.log(checkData([70, 100, 90, 80]))
console.log(checkData([100, 90, 80, 120, 30, 50]))
Vous pouvez également le faire en conservant simplement les valeurs de début et de fin pour les dépôts actuels et les meilleurs, mais ma préférence serait de suivre explicitement les index. Cela me semble plus clair (plus facile à déboguer et à maintenir) de cette façon.
Vous devez itérer le tableau une fois (O(n)
) et conserver un nombre permanent de valeurs min et max et:
function checkData(array) {
var currentmax = array[0];
var currentmin = array[0];
var overallmax = array[0];
var overallmin = array[0];
var i;
for (i = 1; i < array.length; i++) {
if (array[i] <= array[i - 1]) {
// value is same or decreased
currentmin = array[i];
} else {
// check if previous iteration was the largest
if (currentmax - currentmin > overallmax - overallmin) {
overallmax = currentmax;
overallmin = currentmin;
}
// restart
currentmax = array[i];
currentmin = array[i];
}
}
// check if last iteration was the largest
if (currentmax - currentmin > overallmax - overallmin) {
overallmax = currentmax;
overallmin = currentmin;
}
return [overallmax, overallmin, overallmax - overallmin];
}
console.log(checkData([100, 90, 80, 120]));
console.log(checkData([100, 90, 80, 120, 200, 100, 90]));
console.log(checkData([10, 100, 50, 50, 10, 100, 50, 50, 1]));
Il semblerait que vous souhaitiez que les valeurs max et min renvoyées soient les mêmes que celles utilisées pour calculer la plus grande chute au lieu des valeurs max et min globales. Dans ce cas, ajoutez simplement une variable supplémentaire pour stocker celles-ci lorsque drop est mis à jour. Remplacer
drop = Math.max(tempDrop, drop)
avec une instruction if (pseudocode):
if current_drop is greater than stored_drop:
stored_drop = current_drop
stored_max_min = current max and min
puis renvoyez les max et min supplémentaires stockés.
Vous devez suivre deux choses:
i
.i
à la fin de la liste.Ensuite, il vous suffit de trouver la liste déroulante pour chaque index et de sélectionner celui qui est le plus grand.
Voici le code:
function maxDrop (data) {
if (!data || data.length === 0) {
return;
}
const max = [];
const min = [];
for (let i = 0; i < data.length; i++) {
const left = data.slice(0, i);
const right = data.slice(i, data.length);
max.Push(Math.max.apply(null, left));
min.Push(Math.min.apply(null, right));
}
let maxDrop = max[0] - min[0];
let maxValue = max[0];
let minValue = min[0];
for (let j = 0; j < data.length; j++) {
const drop = max[j] - min[j];
if (maxDrop < drop) {
maxDrop = drop;
maxValue = max[j];
minValue = min[j];
}
}
return [maxValue, minValue, maxDrop];
}
console.log(maxDrop([100,90,80,120]))
console.log(maxDrop([100,110,120,300,200,70,60,50,90,400]))
console.log(maxDrop([100,90,80,120,30]))
Pour ajouter une personne de plus au mélange ... Une approche possible consiste à créer d’abord toutes les plages de largage, puis à choisir celle qui présente la plus grande chute
Une version avec réduction:
function checkData(data) {
let dropInd = 1,
mx = data.reduce((arr,val, ind) => {
if(ind && val > data[ind-1])dropInd++;
arr[dropInd] = arr[dropInd] || {max:val};
arr[dropInd].min = val;
arr[dropInd].drop = arr[dropInd].max - val;
return arr;
}, []) //after reduce, islands are created based on 'dropInd'
.sort((v1,v2)=>v2.drop - v1.drop) //sort by drop descending
[0]; //the first value now contains the maximum drop
return [mx.max,mx.min,mx.drop];
}
console.log(checkData([100, 90, 80, 120]));
console.log(checkData([100, 90, 80, 120, 200, 100 ,90]));
console.log(checkData([200,100, 90, 80, 120, 100 ,90]));
console.log(checkData([200,120,190, 90, 80, 120, 100 ,90]));