LeetCode 热题 100之双指针

28 阅读3分钟

283. 移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

 

示例 1:

输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

示例 2:

输入: nums = [0]
输出: [0]

 

提示:

  • 1 <= nums.length <= 104
  • -231 <= nums[i] <= 231 - 1
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int j = 0, n = nums.size();
        for(int i=0; i<n; i++){
            if(nums[i]!=0){
                nums[j++] = nums[i];
            }
        }
        for(; j<n; j++) nums[j] = 0;
    }
};

11. 盛最多水的容器

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明: 你不能倾斜容器。

 

示例 1:

输入: [1,8,6,2,5,4,8,3,7]
输出: 49 
解释: 图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49

示例 2:

输入: height = [1,1]
输出: 1

 

提示:

  • n == height.length
  • 2 <= n <= 105
  • 0 <= height[i] <= 104
class Solution {
public:
    int maxArea(vector<int>& height) {
        int l = 0, r = height.size()-1;
        long long res = 0;
        while(l < r){
            long long t = min(height[l], height[r]) * (long long)(r-l);
            res = max(res, t);
            if(height[l] < height[r]){
                l++;
            }else r--;
        }
        return res;
    }
};

15. 三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

注意: 答案中不可以包含重复的三元组。

 

 

示例 1:

输入: nums = [-1,0,1,2,-1,-4]
输出: [[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1][-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

示例 2:

输入: nums = [0,1,1]
输出: []
解释: 唯一可能的三元组和不为 0 。

示例 3:

输入: nums = [0,0,0]
输出: [[0,0,0]]
解释: 唯一可能的三元组和为 0

 

提示:

  • 3 <= nums.length <= 3000
  • -105 <= nums[i] <= 105
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
       sort(nums.begin(), nums.end());
       int n = nums.size();
       vector<vector<int>> res;
       for(int i=0; i<n; i++){
           if(i >0 && nums[i] == nums[i-1]) continue;
           int l = i+1;
           int r = n-1;
           while(l < r){
               int sum = nums[i] + nums[l] + nums[r];
               if(sum == 0){
                  res.push_back(vector<int>{nums[i], nums[l], nums[r]});
                  while(l < r && nums[l] == nums[l+1]) l++;
                  while(l < r && nums[r] == nums[r-1]) r--;
                  l++;
                  r--;
               }else if(sum < 0){
                   l++;
               }else{
                    r--;
               }
           }
       }
       return res;
    }
};

42. 接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

 

示例 1:

输入: height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6
解释: 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 

示例 2:

输入: height = [4,2,0,3,2,5]
输出: 9

 

提示:

  • n == height.length
  • 1 <= n <= 2 * 104
  • 0 <= height[i] <= 105
class Solution {
public:
    int trap(vector<int>& height) {
        int res = 0, l = 0, r = height.size()-1, pmax = 0, smax = 0;
        while(l < r){
            pmax = max(pmax, height[l]);
            smax = max(smax, height[r]);
            res += pmax < smax ? pmax-height[l++] : smax-height[r--];
        }
        return res;
    }
};