尺取法(一)
尺取法又叫做双指针法。主要分为同向双指针和反向双指针。算法相对二分来说比较简单,是一个单一的算法。没有二分那么容易跟其他的题目进行嵌套。下面主要写一点题目吧。
1.删除排序数组中的重复项
链接: 删除排序数组中的重复项.
解题思路
这是一个比较简单的题,一个典型的同向双指针。i为快指针,j为慢指针。i和j都从头到尾扫描数组a[]。i指针走得快,逐个遍历整个数组;j指针走得慢,它始终指向当前不重复部分的最后一个数。也就是说,j用于获得不重复的数。快指针i++,如果此时a[i]不等于慢指针j指向的a[j],就把j++,并且把a[i]复制到慢指针j的当前位置a[j]。i扫描结束后,a[0]到a[j]就是不重复数组。
题解
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size()==0)
return 0;
int i;
int j=0;
for(i=1;i<nums.size();i++){
if(nums[j]!=nums[i]){
j++;
}
nums[j]=nums[i];
}
return j+1;
}
};
2.水果成篮
链接: 水果成篮.
解题思路
看懂题目的意思后,其实很好理解。就是在数组中找一个最长的子序列,然后里面只有重复的两个元素。返回这个子序列的长度,很显然这是一个双指针的问题。同向双指针。有点困难的地方是j指针如何前进。我测试后是这样操作的。首先当i的值为第三个值(跟a,b都不相等),j等于i-1。然后要考虑j前进太快的问题(tree[j-1]==tree[j]),所以需要一个while循环保证区间最大。举一个例子:[0,1,6,6,4,4,6],这种情况下j的二次更新的时候为3但是很明显tree[2]=tree[3],也就是说j–的区间肯定比较大。
题解
class Solution {
public:
int totalFruit(vector<int>& tree) {
if(tree.size()==0)
return 0;
int i=1;
int j=0;
int ans=0;
int temp;
int a=-1,b=-1;//分别表示两个篮子的水果种类
for(i;i<tree.size();i++){//ab初始化
a=tree[j];
if(tree[i]!=tree[j]){
b=tree[i];
break;
}
}
if(b==-1)//tree里面只有一种水果
return tree.size();
for(i;i<tree.size();i++){
if((tree[i]!=a&&tree[i]!=b)){
temp=i-j;
ans=max(ans,temp);
j=i-1;
while(tree[j-1]==tree[j])//j指针后退保证区间最大
j--;
a=tree[j];
b=tree[i];
}
if(i==tree.size()-1){
temp=i-j+1;
ans=max(ans,temp);
}
}
return ans;
}
};
这个是测试过正确的代码,这个题目的难度是中等。题目需要考虑的特殊情况有两点:1.考虑tree为空。2.考虑tree里面只有一种水果。
写代码还是要考虑周全每种情况。每次都是通过测试来发现错误这样不好。。。