Estoy trabajando en una pregunta de código de lectura y no puedo pensar en una forma de comparar el resto de los elementos de la matriz entre sí. Calculé los números más grandes y más pequeños, pero comparar con el resto de ellos es algo con lo que tengo problemas. A continuación encontrará la pregunta y mi trabajo con ella:

¿Cuántos números son más pequeños que el número actual?

Dados los números de la matriz, para cada número [i] averigüe cuántos números en la matriz son más pequeños que él. Es decir, para cada nums [i] tienes que contar el número de j válidos tales que j! = I y nums [j]

Devuelve la respuesta en una matriz.

Ejemplo 1:

Input: nums = [8,1,2,2,3]
Output: [4,0,1,1,3]
Explanation: 
For nums[0]=8 there exist four smaller numbers than it (1, 2, 2 and 3). 
For nums[1]=1 does not exist any smaller number than it.
For nums[2]=2 there exist one smaller number than it (1). 
For nums[3]=2 there exist one smaller number than it (1). 
For nums[4]=3 there exist three smaller numbers than it (1, 2 and 2).

Mi trabajo:


var smallerNumbersThanCurrent = (nums) => {
    const output = []

    const max = nums.reduce(function(a, b) {
        return Math.max(a, b);
    });

    const min = nums.reduce(function(a, b) {
        return Math.min(a, b);
    });


    for(let i = 0; i < nums.length; i++){
        if(nums[i] === max){
            output.push(nums.length - 1)
        } else if (nums[i] === min){
            output.push(0)
        }
        else if (nums[i] < max && nums[i] > min){
            //how do i compare with rest of the elements in the array?
        
        } 
       }
    }
1
Kazim Shabbir 14 ago. 2020 a las 02:20

5 respuestas

La mejor respuesta

Utilice un bucle anidado.

nums = [8,1,2,2,3];
answer = [];
for (let i = 0; i < nums.length; i++) {
  let count = 0;
  for (let j = 0; j < nums.length; j++) {
    if (nums[j] < nums[i]) {
      count++;
    }
  }
  answer.push(count);
  console.log(`For nums[${i}]=${nums[i]} there are ${count} lower numbers`);
}
console.log(`Answer: ${answer}`);

No es necesario probar i != j ya que un número nunca será menor que él mismo.

1
Barmar 13 ago. 2020 a las 23:32

Una forma mucho más fácil sería simplemente ordenar la matriz, y luego el índice del elemento le dirá cuántos son menos que él:

const nums = [8,1,2,2,3]
const sorted = [...nums].sort();
const result = nums.map((i) => {
    return sorted.findIndex(s => s === i);
});
console.log(result);

Esto tiene el beneficio adicional de que no tiene que buscar en toda la matriz cada número.

1
dave 13 ago. 2020 a las 23:31

Una forma de hacer esto es filtrar la matriz con la condición de que el valor sea menor que el actual y luego contar el número de valores en la matriz filtrada:

const nums = [8,1,2,2,3];

const smallerNums = nums.map(v => nums.filter(n => n < v).length);

console.log(smallerNums); // [4,0,1,1,3]

Alternativamente, puede hacer un recuento en reducir, que debería ser significativamente más rápido:

const nums = [8, 1, 2, 2, 3];

const smallerNums = nums.map(v => nums.reduce((c, n) => c += (n < v), 0));

console.log(smallerNums); // [4,0,1,1,3]
1
Nick 14 ago. 2020 a las 00:57

Inspirado por @tao, hice pruebas de rendimiento de cada solución. En mi computadora (un Intel Core I9-9900 con 64 GB de RAM), la solución de @ StackSlave es consistentemente la más rápida, seguida de la otra solución de clasificación, la solución de reducción, la iteración básica y el filtro. Puede ejecutar las pruebas usted mismo a continuación:

const datalength = 1000;
const iterations = 100;

const getRandom = (min, max) => Math.random() * (max - min) + min;
const data = Array.from({
  length: datalength
}, () => getRandom(1, 100));

const mapper = arr => arr.map(i => arr.filter(n => n < i).length);

const sorter = nums => {
  const sorted = [...nums].sort();
  const result = nums.map((i) => {
    return sorted.findIndex(s => s === i);
  });
};

const iterator = arr => {
  const answer = [];
  for (let i = 0; i < arr.length; i++) {
    let count = 0;
    for (let j = 0; j < arr.length; j++) {
      if (arr[j] < arr[i]) {
        count++;
      }
    }
    answer.push(count);
  }
  return answer;
};

const rankZero = array => {
  const s = [...array],
    r = [];
  s.sort((a, b) => {
    return a - b;
  });
  for (let n of array) {
    r.push(s.indexOf(n));
  }
  return r;
}

const reducer = arr => arr.map(v => arr.reduce((c, n) => c += (n < v), 0));

let fns = {
  'iterator': iterator,
  'mapper': mapper,
  'sorter': sorter,
  'reducer': reducer,
  'rankZero': rankZero
}

for (let [name, fn] of Object.entries(fns)) {
  let total = 0;
  for (i = 0; i < iterations; i++) {
    let t0 = performance.now();
    fn(data);
    let t1 = performance.now();
    total += t1 - t0;
  }
  console.log(name, (total / iterations).toFixed(2));
}
0
Nick 14 ago. 2020 a las 02:01

Me gustaria:

function rankZero(array){
  const s = [...array], r = [];
  s.sort((a, b)=>{
    return a - b;
  });
  for(let n of array){
    r.push(s.indexOf(n));
  }
  return r;
}
console.log(rankZero([8, 1, 2, 2, 3]));
1
StackSlave 13 ago. 2020 a las 23:49