携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第29天,点击查看活动详情
例子:
将一个数组旋转k步,输入一个数组[1,2,3,4,5,6,7],k=3,即旋转3步,输出[5,6,7,1,2,3,4].
两种思路:
1.将末尾的数字pop取出k个,每取出一个数字就unshift放在原数组前。
function fn1(arr:number[],k:number):number[]{
const length = arr.length;
if(!k || length===0) return arr;
const step = Math.abs(k%length); //取绝对值
//时间复杂度O(n^2)
for(let i = 0;i<step;i++){
const n = arr.pop(); //定义n为临时变量,不占用空间,故空间复杂度O(1)
if(n!=null){
arr.unshift(n);//unshift时间复杂度O(n)
}
}
return arr;
}
console.log(fn1([1,2,3,4,5,6,7],3),“fn1”)
2.将后k个元素和前length-k个元素使用slice方法分割开,然后使用concat连接到一起。
function fn2(arr:number[],k:number):number[]{
const length = arr.length;
if(!k || length===0) return arr;
const step = Math.abs(k%length);
//时间复杂度O(1)
const part1 = arr.slice(-step);
//(使用slice方法原数组不变
//所以时间复杂度仍然为O(1))
const part2 = arr.slice(0,length-step);//但额外定义变量比较占用空间
const result = part1.concat(part2);
return result;
}
console.log(fn2([1,2,3,4,5,6,7],3),"fn2")
进行单元测试:打开终端输入npx jest + 代码目录(src/01-单元测试)
describe("数组旋转",()=>{
//每个it都是一次测试
it('正常情况',()=>{
const arr = [1,2,3,4,5,6,7]
const k = 3;
const res = fn1(arr,k)
expect(res).toEqual([5,6,7,1,2,3,4])//断言
})
it('数组为空',()=>{
const res = fn1([],3)
expect(res).toEqual([])//断言
})
it('k是负值',()=>{
const res = fn1([1,2,3,4,5,6,7],-3);
expect(res).toEqual([5,6,7,1,2,3,4]) //断言
})
})
复杂度分析:
思路1:时间复杂度O(n^2),空间复杂度O(1)
思路2:时间复杂度O(1),空间复杂度O(n)
(unshift(O(n)),shift,splice都很慢。影响时间复杂度)
故选择思路二。