力扣75——双指针

总结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],则说明需要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:指针一前一后。

你可能感兴趣的:(算法题,leetcode,算法,c++)