问题描述
数组旋转,输入步数(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();
测试结果图
测试用例
- 测试正常数据下结果
- 测试数组为空
- 测试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完胜!