总结leetcode75中双指针的算法题解题思路。
上一篇:力扣75——数组与字符串
以下代码大部分为本人所写,少部分为官方示例代码。
力扣75——双指针
- 1 移动零
- 2 判断子序列
- 3 K 和数对的最大数目
- 4 盛最多水的容器
- 1-4 解题总结
1 移动零
题目:
给定一个数组 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++]);}}};
2 判断子序列
题目:
给定字符串 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;}};
3 K 和数对的最大数目
题目:
给你一个整数数组 nums 和一个整数 k 。每一步操作中,你需要从数组中选出和为 k 的两个整数,并将它们移出数组。返回你可以对数组执行的最大操作数。
题解:两指针一左一右。先排序,然后用while循环将left和right向中间靠近。
排序。
初始时,left指向最左边,right指向最右边。
如果nums[left]+nums[right]==k
,找到了一个,各自向中间缩进一格。此时可以认为是新的一个数组,继续判断其两端值的和。
如果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;}
};
4 盛最多水的容器
题目:
给定一个长度为 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;}};
1-4 解题总结
题目类型:都是vector或string。
双指针类型1:一个指向最左边,一个指向最右边。
双指针类型2:指针一前一后。