前言
刷题记录第2天,在数组相关题目中,双指针是个很不错的方法。下面5道题能帮助你充分理解双指针在数组中的应用。
一般使用时我记住一句话:快指针指向的是所需要的值则慢指针不动
一、移除元素
本题可以用双指针来解决
当fast指向的值不是要删除的值时,slow指向的值被赋值为fast指向的值,slow和fast均向后移1
当fast指向的值为要删除的值时,slow不动,fast向后移1
总结:快指针指向的是所需要的值则慢指针不动
代码如下
int removeElement(int* nums, int numsSize, int val) {
int fast = 0, slow = 0;
for(fast = 0; fast < numsSize; fast++) {
if (nums[fast] != val) {
nums[slow++] = nums[fast];
}
}
return slow;
}
二、删除有序数组中的重复项
本题本题也可以使用双指针,难度不大
int removeDuplicates(int* nums, int numsSize) {
int fast = 0, slow = 0;
for(fast = 0; fast < numsSize; fast++) {
if (nums[fast] != nums[slow]) {
nums[++slow] = nums[fast];
}
}
return slow+1;
}
这里为什么是 ++slow,我们删除的是重复元素,也就是我们要保留其中1个,++slow就可以解决这个问题。最后结束时slow为新数组最后一个元素的下标,所以返回slow+1 = 新数组的元素个数
三、移动零
本题相当于第一题的变形:删除数组中的0,最后把原数组和新数组差的几个空位全赋值为0
void moveZeroes(int* nums, int numsSize){
int fast = 0, slow = 0;
for (fast = 0; fast < numsSize; fast++) {
if(nums[fast] != 0) {
nums[slow++] = nums[fast];
}
}
int i = 0;
for(i = slow; i < numsSize; i++) {
nums[i] = 0;
}
}
四、比较含退格的字符串
本题可以使用双指针来达成进阶的要求
具体实际代码如下,代码下面有讲解
bool backspaceCompare(char* S, char* T) {
int i = strlen(S) - 1, j = strlen(T) -1;
int S_del = 0, T_del = 0;
while(i >= 0 || j >= 0) {
//遍历S
while(i >= 0) {
if(S[i] == '#') {
S_del++;
i--;
}
else if (S_del > 0) {
S_del--;
i--;
}
else if (S_del == 0) {
break;
}
}//end of while_S
//遍历T
while(j >= 0) {
if(T[j] == '#') {
T_del++;
j--;
}
else if (T_del > 0) {
T_del--;
j--;
}
else if (T_del == 0) {
break;
}
}//end of while_T
//判断
if(i >= 0 && j >= 0) {
if(S[i] != T[j]) {
return false;
}
}
else {
if (i >= 0 || j >= 0) {
return false;
}
}
i--;
j--;
}
return true;
}
五、有序数组的平方
本题主容易的想法是先平方再排序,时间复杂度最优为为O(nlog(n)),本题要完成进阶的目标O(n),可以使用双指针。