Деление четных чисел на 2 и умножение нечетных чисел на 2

Введение

В этой задаче нам дан массив положительных целых чисел, и мы можем выполнять два типа операций над любым элементом массива любое количество раз. Нам нужно минимизировать отклонение массива, которое является максимальной разницей между любыми двумя элементами в массиве.

Подход

Мы можем использовать максимальную кучу, чтобы отслеживать максимальный элемент в массиве. Начнем с умножения всех элементов массива, пока они не станут нечетными. Затем мы ищем наименьший элемент в массиве и делим его на 2. Мы повторяем этот процесс до тех пор, пока не сможем больше делить ни один элемент на 2. Мы вычисляем отклонение на каждом шаге и отслеживаем минимальное отклонение. Как только мы достигли конца, мы возвращаем минимальное отклонение.

Код

Вот код JavaScript для решения:

/**
 * @param {number[]} nums
 * @return {number}
 */
var minimumDeviation = function(nums) {
    let heap = new MaxHeap();
    let minDeviation = Infinity;
    let min = Infinity;
    for(let i=0; i<nums.length; i++){
        if(nums[i]%2 !== 0){
            nums[i] *= 2;
        }
        heap.insert(nums[i]);
        min = Math.min(min, nums[i]);
    }
    while(true){
        let max = heap.extractMax();
        minDeviation = Math.min(minDeviation, max-min);
        if(max%2 === 1){
            break;
        }else{
            heap.insert(max/2);
            min = Math.min(min, max/2);
        }
    }
    return minDeviation;
};

class MaxHeap {
    constructor(){
        this.heap = [];
    }
    insert(value){
        this.heap.push(value);
        this.bubbleUp();
    }
    bubbleUp(){
        let index = this.heap.length-1;
        while(index > 0){
            let parentIndex = Math.floor((index-1)/2);
            if(this.heap[parentIndex] < this.heap[index]){
                [this.heap[parentIndex], this.heap[index]] = [this.heap[index], this.heap[parentIndex]];
                index = parentIndex;
            }else{
                break;
            }
        }
    }
    extractMax(){
        if(this.heap.length === 1){
            return this.heap.pop();
        }else{
            let max = this.heap[0];
            this.heap[0] = this.heap.pop();
            this.sinkDown(0);
            return max;
        }
    }
    sinkDown(index){
        let left = 2*index+1;
        let right = 2*index+2;
        let largest = index;
        if(left < this.heap.length && this.heap[left] > this.heap[largest]){
            largest = left;
        }
        if(right < this.heap.length && this.heap[right] > this.heap[largest]){
            largest = right;
        }
        if(largest !== index){
            [this.heap[index], this.heap[largest]] = [this.heap[largest], this.heap[index]];
            this.sinkDown(largest);
        }
    }
    peek(){
        return this. Heap[0];
    }
}

Анализ сложности

  • Временная сложность: O(n*log(m)), где n — длина массива, а m — максимальный элемент в массиве.
  • Сложность пространства: O(n), так как мы используем кучу для хранения элементов в массиве.

Заключение

В этом сообщении блога мы обсудили проблему Leetcode 1675: минимизировать отклонение в массиве. Мы объяснили наш подход и предоставили код JavaScript для решения. Мы также проанализировали временную и пространственную сложность решения.