双指针查找:使用两个指针,一个遍历数组,一个指向需要操作的地方。直到遍历完数组。
1. 移除数组中的元素
给你一个数组 arr 和一个值 target,移除所有数值等于 target 的元素。要求在原数组删除。
解题思路
1.这个解决方式有很多,可以从后往前遍历,使用splice删除,可以使用正则替换删除。这里使用双指针来删除。
2.创建两个索引,一个遍历数组;一个指向需要改变的位置。
3.最后截取数组到需要改变的位置返回就是需要的数组。
function fn(arr, target) {
let indexOne = 0;
let indexTwo = 0;
while (indexOne < arr.length){
if(arr[indexOne] !== target){
arr[indexTwo] = arr[indexOne];
indexTwo ++;
}
indexOne ++;
}
return arr.slice(0, indexTwo);
}
console.log(fn([1,2,3,3,4,5,4,3,3,6], 3));
上面的写法还可以如下
function fn(arr, target) {
let indexTwo = 0;
for(let i=0;i<arr.length;i++){
if(arr[i] !== target){
arr[indexTwo] = arr[i];
indexTwo ++;
}
}
return arr.slice(0, indexTwo);
}
2. 给有序数组的平方排序
已知有序数组 [-4,-1,0,3,10],给每个值平方组成的数组排序。要求时间复杂度O(n)。
2-1. 解法1
思路
- 因为已知有序,那么复数部分平方后是单调递减。正数部分单独递增。
- 拆分为一个正数一个复数的数组,然后处理负数平方后颠倒和正数平方两个数组。
- 两个数组分别给个指针ab,从第一个开始。当a的值小于b的值,将a的值添加到结果数组,a+=1; 同理,b值更小时添加b的值,b+=1;相等你爱算那边就那边,无所谓。当两个数组都遍历完结束(我 这里是有一个遍历完将另一个剩余的添加进来,结束)
- 第一个函数是使用二分查找查到正负分界。二分查找可以看我另一篇介绍
function searSplit(arr) {
let leftIndex = 0;
let rightIndex = arr.length - 1;
let middle;
while (leftIndex <= rightIndex) {
middle = Math.floor((leftIndex + rightIndex) / 2);
if(leftIndex === rightIndex){
return arr[middle] ===0 ? middle : leftIndex
}
if(0 > arr[middle]){
leftIndex = middle + 1
}else{
rightIndex = middle
}
}
}
function fn(arr) {
// 如果存在负数,找到分界点最右边小于0的数
if (arr[0] < 0) {
let splitIndex;
splitIndex = searSplit(arr);
let leftArr = arr.slice(0, splitIndex);
leftArr.sort((a,b) => b-a);
leftArr = leftArr.map(item => item * item);
let rightArr = arr.slice(splitIndex);
rightArr = rightArr.map(item => item * item);
let leftIndex = 0;
let rightIndex = 0;
let result = []
while (leftIndex <= leftArr.length - 1 || rightIndex <= rightArr.length - 1) {
let leftVal = leftArr[leftIndex];
let rightVal = rightArr[rightIndex];
if(leftIndex>=leftArr.length){
return result.concat(rightArr.slice(rightIndex))
}
if(rightIndex>=rightArr.length){
console.log(leftIndex)
return result.concat(leftArr.slice(leftIndex))
}
if(leftVal < rightVal){
leftIndex ++
result.push(leftVal)
}else if(leftVal > rightVal ) {
rightIndex ++;
result.push(rightVal);
}else{
leftIndex ++;
result.push(leftVal);
}
}
return result;
}
return arr.map(item => item * item);
}
console.log(fn([-4, -1, 0, 3, 10]))
2-2. 解法二
思路
1.因为是个有序数组,那么每个平方后,前面部分是递减,后一部分是递增。 2.使用双指针,一个指向开始一个指向末尾。创建一个空数组用于存放最后的结果。 3.比较两个指正对应值得大小,大的unshift进数组,相应大的指针往中间移动。 4.不断重复上面,知道两个指针相等保存最后一个值停止。
function fn(arr) {
arr = arr.map(item => item * item);
let leftIndex = 0;
let rightIndex = arr.length - 1;
let result = [];
while (leftIndex<=rightIndex){
if(arr[leftIndex] > arr[rightIndex]){
result.unshift(arr[leftIndex]);
leftIndex++;
} else{
result.unshift(arr[rightIndex]);
rightIndex--;
}
}
return result
}
console.log(fn([-4,-1,1,3,10]));