双指针法
双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
定义快慢指针
- 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
- 慢指针:指向更新 新数组下标的位置
相关题目
删除有序数组中的重复项
解题思路:
解法: 双指针
首先注意数组是有序的,那么重复的元素一定会相邻。
要求删除重复元素,实际上就是将不重复的元素移到数组的左侧。
考虑用 2 个指针,一个在前记作 p,一个在后记作 q,算法流程如下:
1.比较 p 和 q 位置的元素是否相等。
如果相等,q 后移 1 位
如果不相等,将 q 位置的元素复制到 p+1 位置上,p 后移一位,q 后移 1 位
重复上述过程,直到 q 等于数组长度。
返回 p + 1,即为新数组长度。
class Solution {
public int removeDuplicates(int[] nums) {
if(nums == null || nums.length == 0) return 0;
int p = 0;
int q = 1;
while(q < nums.length){
if(nums[p] != nums[q]){
nums[p + 1] = nums[q];
p++;
}
q++;
}
return p + 1;
}
}
移动零
有一个比较凑巧的思路,那就是知道后面是0 ,那么就去补0
class Solution {
public void moveZeroes(int[] nums) {
int slow=0;
for(int fast=0;fast<nums.length;fast++){
if(nums[fast]!=0){
nums[slow++]=nums[fast];
}
}
for( int num=slow;num<nums.length;num++){
nums[num]=0;
}
}
}
另一种思路就是今天讲的双指针法,一个快指针指要交换的元素,一个满指针指元素接下来位置的下标,设计到元素的交换
class Solution {
public void moveZeroes(int[] nums) {
int n = nums.length, left = 0, right = 0;
while (right < n) {
if (nums[right] != 0) {
swap(nums, left, right);
left++;
}
right++;
}
}
public void swap(int[] nums, int left, int right) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
}
}
比较含退格的字符串
思路:双指针: 遇到字母两指针都向前一位,遇到#号快指针向前一位,慢指针后退一位(注意0位置) 就行了。
这个思路好理解,我自己也想出来了,就是灵活运用双指针的思路,一定记住加上i>0的判断之后然后后移,避免出现第一个字符量就是#,不加上就会数组越界
class Solution {
public boolean backspaceCompare(String s, String t) {
char[] ss = s.toCharArray();
char[] tt = t.toCharArray();
return helper(ss).equals(helper(tt));
}
String helper(char[] c){
int i = 0,j = 0;
while(j < c.length){
if(c[j] != '#'){ //遇到字母 两个指针都往前走
c[i++] = c[j++];
}else {
j++;
if(i > 0) i--; // 遇到 #, i 指针向后退
}
}
return new String(c).substring(0,i);
}
}
这个地方数组字符串之间的转换要熟练把握。
有序数组的平方
这个题目不使用双指针的思路去做
class Solution {
public int[] sortedSquares(int[] nums) {
for(int i=0;i<nums.length;i++){
nums[i]=nums[i]*nums[i];
}
Arrays.sort(nums);
return nums;
}
}
使用双指针的思路去做,
在评论区看到一个这道题用双指针的解法分析的很清晰的,
class Solution {
public int[] sortedSquares(int[] nums) {
// 左指针,指向原数组最左边
int left = 0;
// 有指针,指向原数组最右边
int right = nums.length - 1;
// 创建一个新数组,存储平方值
int[] result = new int[nums.length];
// 得到元素值平方值,从新数组最后位置开始写
int write = nums.length - 1;
// 左右指针相遇(逐渐靠拢的过程)之后不再循环
while (left <= right){
// 如果原数组的左指针对应的平方值大于右指针,那么往新数组最后位置写入左指针对应的平方值
if (nums[left] * nums[left] > nums[right] * nums[right]){
result[write] = nums[left] * nums[left];
// 左指针右移
left ++;
// 移动新数组待写入的位置
write --;
}
else {
result[write] = nums[right] * nums[right];
right --;
write --;
}
}
return result;
}
}