双指针一般有两种case:
1. 快慢指针,一般排序需要使用快慢指针,快慢指针有两种游走方式:1.快指针一直往前,不归位;2. 慢指针移动时,快指针归位。
2. 收尾指针,一般回文、对称性判断需要使用首尾指针
双指针中,快慢指针问题:
1. 指针一快一慢,快指针按序遍历数组,慢指针记录有效数据位置。
2. 当快指针找到有效数据时,慢指针才往前走一步;
给你一个整数数组 arr 。请你将数组中的元素按照其二进制表示中数字 1 的数目升序排序。
如果存在多个数字二进制中 1 的数目相同,则必须将它们按照数值大小升序排列。
请你返回排序后的数组
/**
* @param {number[]} nums
* @param {number} val
* @return {number}
*/
var removeElement = function(nums, val) {
let curIndex = 0;
for(let compareIndex = 0; compareIndex< nums.length; compareIndex++){
if(nums[compareIndex] !==val){
nums[curIndex++] = nums[compareIndex];
}
}
return curIndex;
};
给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
/**
* @param {number[]} nums
* @return {number}
*/
var removeDuplicates = function(nums) {
let curIndex =0 ;
// 注意是有序的数组,所以游走指针可以一直向前走。
for(let compareIndex=1; compareIndex < nums.length; compareIndex++)
{
if(nums[curIndex] !== nums[compareIndex]){
nums[++curIndex] = nums[compareIndex];
}
}
return curIndex+1;
};
给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。
函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。
说明:
返回的下标值(index1 和 index2)不是从零开始的。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
答题思路:
1. 数组是有序的,从大到小。 因此当某个值和第一个值的和大于target时,这个值右边及本身都不用考虑了,跟谁加都会大于目标值。只用考虑这个值左边的数据,因此要先找到这个中介值的index。
2. 快慢指针从中介值开始从右往左移动。 慢指针值是当前大值,快指针移动寻找一个小值与其相加。
若相机大于目标值,则快指针继续向左移动寻找更小的值;
若相加小于目标值,说明当前固定的大值无匹配小值与之相加可得目标值,因此直接向左移动慢指针换固定值,快指针指回慢指针的下一步,重新开始寻找小值;
若相等,则为返回快慢指针位置。注意要加1,因为题目要求索引不是从0开始
/**
* @param {number[]} numbers
* @param {number} target
* @return {number[]}
*/
var twoSum = function(numbers, target) {
let maxIndex = numbers.findIndex(num => num + numbers[0]> target);
if(maxIndex === -1) maxIndex = numbers.length;
secondIndex = maxIndex - 1;
firstIndex = secondIndex-1;
while(secondIndex >0){
if(firstIndex<0){
secondIndex--;
firstIndex= secondIndex-1;
}else{
const total = numbers[firstIndex] + numbers[secondIndex];
if(total < target){
secondIndex --;
firstIndex= secondIndex-1;
}else if(total > target){
firstIndex--;
}else{
return [firstIndex+1, secondIndex+1];
}
}
}
return [];
};