算法练习 - 01 数字旋转

172 阅读2分钟

问题描述

数组旋转,输入步数(step),根据输入的值对数组进行旋转。例如原数组为[1,2,3,4,5],输入setp为3,则结果返回[3,4,5,1,2]

问题解析

算法rotate1

  • 对步数进行循环for
  • 每次循环拿出数组最后一个元素pop
  • 插入到数组最前方unshift
  • 返回数组

算法复杂度

  • 时间复杂度: O(n^2)
  • 空间复杂度: O(1)
/**
 * 数组旋转 Array Rotate1
 * @author 小恐龙
 */
export function rotate1(array: number[], step: number): number[] {
    //如果不是数组或者数组长度是0直接返回原数组
    if (array.length === 0 || !Array.isArray(array)) return array;
    step = Math.abs(step);
    for (let i = 0; i < step; i++) {
        let stepItem = array.pop();
        if (stepItem) {
            array.unshift(stepItem);
        }
    }
    return array;
}

算法rotate2

  • 根据步数直接从后面截取要旋转至前方的数组
  • 截取步数之前剩下的数组
  • 拼接旋转到前方的数组和剩下的数组
  • 返回结果

算法复杂度

  • 时间复杂度: O(1)
  • 空间复杂度: O(n)
/**
 * 数组旋转 Array Rotate2
 * @author 小恐龙
 */
export function rotate2(array: number[], step: number): number[] {
    let arrLength = array.length;
    //如果不是数组或者数组长度是0直接返回原数组
    if (array.length === 0 || !Array.isArray(array)) return array;
    step = Math.abs(step % array.length);
    let startArr = array.slice(-step);
    let endArr = array.slice(0, arrLength - step);
    return startArr.concat(endArr);
}

测试大数据情况下耗时

制造数组内容为[1,2,3,4,...,10*10000]的数组,测试在大数据的情况下两种算法的耗时时间。

/**
 * 大数据测试代码
 */
function bigDataTest() {
    let arrayLength = 10 * 10000;
    let step = 6 * 10000;
    let arr1 = [];
    for (let i = 0; i < arrayLength; i++) {
        arr1.push(i);
    }
    console.time("rotate1");
    let rotate1Result = rotate1(arr1, step);
    console.timeEnd("rotate1");
    console.log(
        "🚀 ~ file: array-rotate.ts ~ line 38 ~ bigDataTest ~ rotate1Result",
        rotate1Result
    );
    let arr2 = [];
    for (let i = 0; i < arrayLength; i++) {
        arr2.push(i);
    }
    console.time("rotate2");
    let rotate2Result = rotate2(arr2, step);
    console.timeEnd("rotate2");
    console.log(
        "🚀 ~ file: array-rotate.ts ~ line 38 ~ bigDataTest ~ rotate1Result",
        rotate2Result
    );
}
bigDataTest();

测试结果图

iShot_2022-05-20_17.26.36.png

测试用例

  • 测试正常数据下结果
  • 测试数组为空
  • 测试step是负值
  • 测试step不是数字
  • 测试step是0
  • 测试step大于数组长度
/**
 * @description array rotate test
 */
import { rotate1, rotate2 } from "./array-rotate";

describe("数组旋转 - rotate1 测试", () => {
    it("正常情况", () => {
        const arr = [1, 2, 3, 4, 5, 6];
        const step = 3;
        const res = rotate1(arr, step);
        expect(res).toEqual([4, 5, 6, 1, 2, 3]);
    });
    it("数组空的情况", () => {
        const res = rotate1([], 3);
        expect(res).toEqual([]);
    });
    it("不是数组的情况", () => {
        //@ts-ignore
        const res = rotate1({}, 3);
        expect(res).toEqual([]);
    });
    it("step 负数情况", () => {
        const arr = [1, 2, 3, 4, 5, 6];
        const step = -3;
        const res = rotate1(arr, step);
        expect(res).toEqual([4, 5, 6, 1, 2, 3]);
    });
    it("step = 0 ", () => {
        const arr = [1, 2, 3, 4, 5, 6];
        const step = 0;
        const res = rotate1(arr, step);
        expect(res).toEqual(arr);
    });
    it("step大于数组长度 ", () => {
        const arr = [1, 2, 3, 4, 5, 6];
        const step = 9;
        const res = rotate1(arr, step);
        expect(res).toEqual([4, 5, 6, 1, 2, 3]);
    });
    it("step 不是数字 ", () => {
        const arr = [1, 2, 3, 4, 5, 6];
        const step = "test";
        //@ts-ignore
        const res = rotate1(arr, step);
        expect(res).toEqual(arr);
    });
});

describe("数组旋转 - rotate2 测试", () => {
    it("正常情况", () => {
        const arr = [1, 2, 3, 4, 5, 6];
        const step = 3;
        const res = rotate2(arr, step);
        expect(res).toEqual([4, 5, 6, 1, 2, 3]);
    });
    it("step 负数情况", () => {
        const arr = [1, 2, 3, 4, 5, 6];
        const step = -3;
        const res = rotate2(arr, step);
        expect(res).toEqual([4, 5, 6, 1, 2, 3]);
    });
    it("数组空的情况", () => {
        const res = rotate2([], 3);
        expect(res).toEqual([]);
    });
    it("不是数组的情况", () => {
        //@ts-ignore
        const res = rotate2({}, 3);
        expect(res).toEqual([]);
    });
    it("step = 0 ", () => {
        const arr = [1, 2, 3, 4, 5, 6];
        const step = 0;
        const res = rotate2(arr, step);
        expect(res).toEqual(arr);
    });
    it("step大于数组长度 ", () => {
        const arr = [1, 2, 3, 4, 5, 6];
        const step = 9;
        const res = rotate2(arr, step);
        expect(res).toEqual([4, 5, 6, 1, 2, 3]);
    });
    it("step 不是数字 ", () => {
        const arr = [1, 2, 3, 4, 5, 6];
        const step = "test";
        //@ts-ignore
        const res = rotate2(arr, step);
        expect(res).toEqual(arr);
    });
});

结论

时间复杂度为O(1)的算法rotate2完胜!