双指针法是处理数组、字符串问题常用的算法。
先用题目引入: 27.移除元素
给你一个数组 nums ,移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并修改输入数组**。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
暴力解法
首先可以用暴力解法:用两层循环:外层循环用于遍历数组找到数值等于val的元素,内层循环从该元素开始后一位元素提前一位,即数值等于val的元素会被其后一位覆盖。
Js代码如下:
var removeElement = function(nums, val) {
var size=nums.length;
var i=0;
while(i<size){
if(nums[i]==val){
for(var k=i;k<size-1;k++){
nums[k]=nums[k+1];
}
size=size-1;
i=0;
}
else i++;
}
return size;
};
双指针法
使用双指针法可以降时间复杂度为O(n):快指针用于甄别数值等于val的元素,慢指针指向要更新的位置。 代码:i为快指针,只要找到不需要移除的元素,就赋值给k(慢指针)所在位置的元素,而后k增加用于更新下一个元素。
var removeElement = (nums, val) => {
let k = 0;
for(let i = 0;i < nums.length;i++){
if(nums[i] != val){
nums[k++] = nums[i]
}
}
return k;
};
相关问题
思路:因为题目中是非严格递增数组,所以判断是否重复只需要前后比较。快指针找到不与前面重复的元素,将其赋值给慢指针自增后指向的索引位置。
var removeDuplicates = function(nums) {
var k=0;
for(var i=1;i<nums.length;i++){
if(nums[k]!=nums[i]){
nums[++k]=nums[i];
}
}
return k+1;
};
思路:由于题目要求所有的零移到最后面,不改变其他元素顺序,所以用快指针来指向不是0的元素,慢指针指向0元素,当该条件发生时,两个元素互换位置(将0换到后面),慢指针前进一位。
var moveZeroes = function(nums) {
var k=0;
for(var i=1;i<nums.length;i++){
if(nums[k]==0 && nums[i]!=0){
var temp=nums[k];
nums[k]=nums[i];
nums[i]=temp;
k++;
}
else if(nums[k]!=0) k++;
}
return nums;
};
思路:1.字符串不能像数组一样通过索引修改单个字符值,所以要先将其转换成数组。2.用下标-1实现“退格”动作。3.注意由于快指针是从1开始的,所以要先对最开头是退格符的情况作处理。4.对处理后返回的新数组和实际长度(k1,k2),判断是否一致。
function dealWithArray(arr){
var k=0;
if(arr[0]=='#'){
arr[0]=null;
k=-1;
}
for(var i=1;i<arr.length;i++){
if(arr[i]!='#'){
k++;
arr[k]=arr[i];
}
else{
if(k>0) k--;
else {
arr[0]=null;
k=-1;
}
}
}
return k;
}
var backspaceCompare = function(s, t) {
var s_arr=s.split('');
var t_arr=t.split('');
var k1=dealWithArray(s_arr);
var k2=dealWithArray(t_arr);
if(k1!=k2) return false;
else{
if(k1==-1) return true;
for(var i=0;i<=k1;i++){
if(s_arr[i]!=t_arr[i]) return false;
}
return true;
}
};