持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情
前言
今天的题目为简单,题目存在者能够取巧的方式,但是用这种方式肯定是不可行的,双指针的解法很有意思,值得去多多思考和理解。
每日一题
今天的题目是 1089. 复写零,难度为简单
-
给你一个长度固定的整数数组 arr,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。
-
注意:请不要在超过该数组长度的位置写入元素。
-
要求:请对输入的数组 就地 进行上述修改,不要从函数返回任何东西。
示例 1:
输入:[1,0,2,3,0,4,5,0]
输出:null
解释:调用函数后,输入的数组将被修改为:[1,0,0,2,3,0,0,4]
示例 2:
输入:[1,2,3]
输出:null
解释:调用函数后,输入的数组将被修改为:[1,2,3]
提示:
- 1 <= arr.length <= 10000
- 0 <= arr[i] <= 9
题解
模拟
题目要求要在原数组上面做出修改,本意是我们不能够改变原数组的引用,是能够通过数组方法来改变这个数组的值
那么和我们之前比较相似的解决思路就是,我们新建一个数组用来保存答案,然后最后在把这个数组的值和原来的做一个比较,修改掉原来的数组,只不过这样肯定是会浪费掉更多的性能的。
如果能够用一个新的数组来进行保存,那么我们就可以先不用在意旧数组内部是什么,只要碰到了0这个元素,就向新数组中push两次0,一直到新数组的个数和旧数组相同为止,然后我们在利用新数组来更新旧数组。
/**
Do not return anything, modify arr in-place instead.
*/
function duplicateZeros(arr: number[]): void {
const n = arr.length
const newArr = []
for(let i = 0; newArr.length < n ; i++){
if(newArr.length == n) break
if(arr[i]==0 && newArr.length!=n-1){
newArr.push(arr[i])
newArr.push(0)
}else{
newArr.push(arr[i])
}
}
newArr.forEach((e,i)=>{
arr[i] = e
})
};
双指针
像上面我们是使用了取巧的方法,但是本质上,是通过记录下一个长度和原数组相同的数组,然后返回来更新原数组,那么我们有没有办法不记录下这个数组,通过别的方式来保留这些状态呢,当然是有的,我们可以通过双指针来进行这一操作,首先通过一个元素记录下我们遍历的长度,然后拿着这个这个值就相当于判断我们当前的新数组是否到达了原数组的长度,碰到正常的元素就加一,碰到零就加二。
然后当这个元素长度到达原数组的长度以后,我们能够拿另一个元素记录下原数组遍历过了几个,然后反过来,通过这个个数,我们就能够知道,新的数组的末尾是原数组的第几个元素,并且当碰到0的时候,需要修改两位。
/**
Do not return anything, modify arr in-place instead.
*/
function duplicateZeros(arr: number[]) {
let i = 0;
let n = arr.length
let j = n - 1;
let k = n - 1;
while (i < j) {
if (arr[i++] === 0) {
j--
}
}
if (i === j) {
arr[k] = arr[j];
k--;
j--;
}
while (j >= 0) {
if (arr[j] === 0) {
arr[k] = 0;
k--;
}
arr[k] = arr[j];
k--;
j--
}
};