总结leetcode75中双指针的算法题解题思路。
上一篇:力扣75——数组与字符串
以下代码大部分为本人所写,少部分为官方示例代码。
题目:
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
题解:两指针一前一后。left指向非零子序列的下一个位置,right指向正在检查的位置。
用right遍历一遍,如果元素非零,将该元素放到left的位置,然后left+1。
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int ns = nums.size();
if (ns < 2) return;
int left = 0;
for (int right = 0; right < ns; ++right) {
if (nums[right] != 0) swap(nums[right], nums[left++]);
}
}
};
题目:
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置
形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。
题解:两指针分别指向一个s和t。
class Solution {
public:
bool isSubsequence(string s, string t) {
int sidx = 0, tidx = 0, ssize = s.size(), tsize = t.size();
if (ssize > tsize) return false;
while (sidx < ssize &&tidx < tsize) {
if (t[tidx] == s[sidx]) sidx++;
tidx++;
}
return sidx == ssize;
}
};
题目:
给你一个整数数组 nums 和一个整数 k 。
每一步操作中,你需要从数组中选出和为 k 的两个整数,并将它们移出数组。
返回你可以对数组执行的最大操作数。
题解:两指针一左一右。先排序,然后用while循环将left和right向中间靠近。
排序。
初始时,left指向最左边,right指向最右边。
如果nums[left]+nums[right]==k
,找到了一个,各自向中间缩进一格。此时可以认为是新的一个数组,继续判断其两端值的和。
如果nums[left]+nums[right]
nums[right]
已经是最大值,所以只能移动left到下一位。此时可以认为是新的一个数组,继续判断其两端值的和。
如果nums[left]+nums[right]>k
,则说明需要nums[left]或nums[right]的值小才能满足条件,由于nums[left]
已经是最小值,所以只能移动right到下一位。此时可以认为是新的一个数组,继续判断其两端值的和。
class Solution {
public:
int maxOperations(vector<int>& nums, int k) {
sort(nums.begin(), nums.end());
int left = 0, right = nums.size() - 1;
int res = 0;
while (left < right) {
if (nums[left] + nums[right] == k) {
res++;
left++;
right--;
} else if (nums[left] + nums[right] > k) {
right--;
} else {
left++;
}
}
return res;
}
};
题目:
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
题解:两指针一左一右。
用nmax记录遍历过的最大储水量。
如果height[left] < height[right],则
(right - left)*(min(height[left], height[right]))
= (right - left)*(height[left])
> ((right-1) - left)*(height[left])
>= ((right-1) - left)*(min(height[left], height[right-1]))
所以right-1是没有必要的,left+1。
如果height[left] > height[right]同理。
class Solution {
public:
int maxArea(vector<int>& height) {
int left = 0, right = height.size()-1,nmax = 0;
int tmp = 0;
while (left < right) {
tmp = (right - left)*(min(height[left], height[right]));
nmax = max(tmp, nmax);
if (height[left] < height[right]) left++;
else right--;
}
return nmax;
}
};
题目类型:都是vector或string。
双指针类型1:一个指向最左边,一个指向最右边。
双指针类型2:指针一前一后。