HackerRank — минимальное время замены 2

#javascript #arrays #performance #sorting

#javascript #массивы #Производительность #сортировка

Вопрос:

Эта задача требует, чтобы вы нашли минимальное количество замен, чтобы отсортировать массив перемешанных последовательных цифр в порядке возрастания. Пока что мой код проходит большинство тестов, однако есть четыре, которые завершаются неудачей из-за тайм-аута. Кто-нибудь может объяснить, почему у моего кода истекает время ожидания? Есть ли способ заставить его быстрее находить ответ?

 function minimumSwaps(arr) {
const min = Math.min(...arr);
let swapCount = 0;
const swap = (array, a, b) => {
    let test = array[a];
    array[a] = array[b];
    array[b] = test;
}
for(let i=0; i<arr.length; i  ){
    if(arr[i]!==i min){
        swap(arr, i, arr.indexOf(i min));
        swapCount  ;
    }
}
return swapCount;
}
  

Я подумал, что это хорошее решение, поскольку ему нужно выполнить итерацию по длине массива только один раз? Я хотел бы иметь возможность понять, почему это работает недостаточно хорошо

Комментарии:

1. Подумайте, насколько это повлияет на производительность, но при работе с большими массивами лучше всего создать переменную для длины массива, чтобы к array.length свойству обращались только один раз.

2. к сожалению, @Ameer не совсем сработал, но спасибо за совет по оптимизации! С этого момента я буду использовать это.

Ответ №1:

Ваша большая проблема связана с вызовом arr.indexOf , поскольку он должен сканировать весь массив каждый раз, когда вы выполняете обмен. Вы можете обойти это, сгенерировав обратный поиск из значения в индекс массива перед началом сортировки, а затем сохранив этот список во время сортировки. Обратите внимание, что вам не нужно выполнять полную замену, просто скопируйте значение из arr[i] в его правильное место в массиве, поскольку вы не возвращаетесь к числу после его передачи. Также вам не нужно min , так как по условиям вопроса оно гарантированно равно 1, и вам не нужно смотреть на последнее значение в массиве, поскольку к тому времени, когда вы до него доберетесь, оно должно быть правильным.

 function minimumSwaps(arr) {
  const indexes = arr.reduce((c, v, i) => (c[v] = i, c), []);
  const len = arr.length - 1;
  let swapCount = 0;
  for (let i = 0; i < len; i  ) {
    if (arr[i] !== i   1) {
      arr[indexes[i 1]] = arr[i];
      indexes[arr[i]] = indexes[i 1];
      swapCount  ;
    }
  }
  return swapCount;
}

console.log(minimumSwaps([7, 1, 3, 2, 4, 5, 6]));
console.log(minimumSwaps([4, 3, 1, 2]));
console.log(minimumSwaps([2, 3, 4, 1, 5]));
console.log(minimumSwaps([1, 3, 5, 2, 4, 6, 7]));  

Ответ №2:

Я думаю, мы должны перевернуть функцию, а не функцию поиска.

 function minimumSwaps($arr) {
$outp = 0;
$result = array_flip($arr);
for($i=0; $i<count($arr); $i  ){
   if($arr[$i] != $i  1){
        $keyswp = $result[$i   1];
        $temp = $arr[$i];
        $arr[$i] = $i   1;
        $arr[$keyswp] = $temp; 
        $tempr = $result[$i   1];
        $result[$i   1] = $i  1;
        $result[$temp] = $keyswp;
        $outp = $outp   1;
    } 
}
return $outp;     
  

}

Ответ №3:

Вот мое решение, оно похоже на решение Nick , за исключением того, что вместо массива.Метод Proptytype.indexOf Я использовал объектный литерал для сопоставления индексов каждого значения для лучшей временной сложности, поскольку поиск в объектном литерале равен O (1) (вы также можете использовать карты ES6). Вот код

 function minimumSwaps(arr) {
    
    let count = 0;
    let search = arr.reduce((o, e, i) => {
        o[e] = i
        return o
    }, {})
    
    

    for(let i =0 ; i < arr.length - 1; i  ){
        let j = search[i 1]
        
        if(arr[i] !== i 1) {
            [arr[i], arr[j]] = [arr[j], arr[i]]
            
            search[arr[i]] = i;
            search[arr[j]] = j;
            count  = 1
        }
        
    }
    
    console.log(arr)
    return count
} 
  

Ответ №4:

Как предлагали другие, вам не следует использовать indexOf метод, поскольку он создает ваше решение O(n^2) (поскольку indexOf метод должен снова сканировать весь массив). Вы можете заранее создать массив карт позиций и использовать его позже во время обмена. Это сохранит линейность вашего решения. Вот подробное объяснение и решение проблемы минимальной замены 2 HackerRank в java, c, c и js с использованием этого метода.