Como Rotacionar um Array em k Passos

Dada uma array [1,2,3,4,5,6,7] e k = 3, a rotação de 3 passos resultaria em [5,6,7,1,2,3,4]

Abordagens de Solução

Abordagem 1: Remover elementos do final e inserir no início

Iremos remover os últimos k elementos e adicioná-los um por um no início da array

Aobrdagem 2: Dividir e combinar

Separar a array em duas partes e combiná-las em ordem invertida

Implementações em Código

Abodragem 1: Usando pop e unshift


/**
 * Rotaciona uma array por k passos utilizando pop e unshift
 * @param array A array original
 * @param k Número de passos de rotação
 * @returns A array rotacionada
 */
export function rotacionarMetodo1(array: number[], k: number): number[] {
    const tamanho = array.length;
    if (!k || tamanho === 0) {
        return array;
    }
    
    // Tratando casos onde k é negativo ou maior que o tamanho da array
    const passos = Math.abs(k % tamanho);
    
    // Complexidade de tempo: O(n²) devido ao unshift dentro do loop
    // Complexidade de espaço: O(1)
    for (let i = 0; i < passos; i++) {
        const elemento = array.pop();
        if (elemento !== undefined) {
            array.unshift(elemento); // unshift tem complexidade O(n)
        }
    }
    
    return array;
}

Abordagem 2: Usando slice e concat


/**
 * Rotaciona uma array por k passos utilizando slice e concat
 * @param array A array original
 * @param k Número de passos de rotação
 * @returns A array rotacionada
 */
export function rotacionarMetodo2(array: number[], k: number): number[] {
    const tamanho = array.length;
    if (!k || tamanho === 0) {
        return array;
    }
    
    const passos = Math.abs(k % tamanho);
    // Complexidade de tempo: O(n)
    // Complexidade de espaço: O(n)
    const parteFinal = array.slice(-passos); // Últimos k elementos
    const parteInicial = array.slice(0, tamanho - passos); // Elementos restantes
    const resultado = parteFinal.concat(parteInicial);
    
    return resultado;
}

Análise de Complexidade

Complexidade de Tempo

  • Abordagem 1: O(n²) - Embora haja apenas um loop, cada operação unshift tem complexidade O(n)
  • Abordagem 2: O(n) - As operações slice e concat são lineares

Complexidade de Espaço

  • Abordagem 1: O(1) - Modifica a array original sem criar estruturas adicionais
  • Abordagem 2: O(n) - Cria novas arrays durante o processo

Testes de Desempenho

Código de Teste


import { rotacionarMetodo1, rotacionarMetodo2 } from './array-rotate';

const arrayTeste = [];
for (let i = 0; i < 100000; i++) {
    arrayTeste.push(i);
}

console.time('rotacionarMetodo1');
rotacionarMetodo1(arrayTeste, 90000);
console.timeEnd('rotacionarMetodo1'); // ~546ms

console.time('rotacionarMetodo2');
rotacionarMetodo2(arrayTeste, 90000);
console.timeEnd('rotacionarMetodo2'); // ~1ms

Resultado

Os testes demonstram que a Abordagem 2 é significativamente mais rápida que a Abordagem 1 para arrays grandes.

Tags: Array Algoritmos TypeScript rotação complexidade

Publicado em 6-20 02:14