方法一 splice:
通过数组的slice方法,碰到 0就在后面加一个0,最后截取原数组的长度,舍弃后面部分。
但这样做是违反了题目的要求,不要在超过该数组长度的位置写入元素。
var duplicateZeros = function(arr) {
var len = arr.length
for(let i=0;i<len;i++){
if(arr[i]===0){
arr.splice(i,0,0)
i++
}
}
arr.splice(len)
};
消耗时间和内存情况:
方法二 ——方法一优化:
不直接操作arr,将arr的字符串形式赋值给str,对str按照要求进行修改,然后将str按位赋值给arr
这种方法也是算取巧
var duplicateZeros = function(arr) {
var str = arr.join('').replaceAll('0','00')
for(var i=0;i<arr.length;i++){
arr[i]=str[i]
}
};
消耗时间和内存情况:
方法三 两次遍历+双指针( 时间复杂度O(n) 空间复杂度O(1) )
用实例来说明:
arr =[0,1,7,6,0,2,0,7],arr里面虽然有3个0,但是前面两个0被复写完之后第三个0就被舍弃了,所以第一次遍历记录arr里有多少个0能被复写,并记录最后一个能被复写的0的位置
双指针left和right,right指向数组的末尾,left指向能被保留下来的最后一个元素,那么(left,right]之间的元素都是要被舍弃的。
如果left指向的是非0元素,那么就把left指向的元素移动到right处,left、right都往前移动一位
如果left指向的是0元素,则看这个0是不是能被复写的0,如果不是就按照非0元素处理,如果是则right以及right-1的位置都要被赋值为0
两次单层循环,没有使用其他数组或字符串,这应该才是最为理想的解法
var duplicateZeros = function(arr) {
var right = arr.length-1,left=0,count
for(let i=0;i<arr.length;i++){
if(arr[i]===0 && right-i>left){
left++
count=i
}
}
left = right-left
while(left>=0){
if(arr[left]===0 && left<=count){
arr[right]=0
right--
arr[right]=0
right--
left--
}else{
arr[right]=arr[left]
right--
left--
}
}
};
消耗时间和内存情况: