当前位置: 首页 > news >正文

Leetcode 刷题记录 02 —— 双指针

本系列为笔者的 Leetcode 刷题记录,顺序为 Hot 100 题官方顺序,根据标签命名,记录笔者总结的做题思路,附部分代码解释和疑问解答。

目录

01 移动零

02 盛最多水的容器

03 三数之和

04 接雨水


01 移动零

//双指针法
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        //左指针指向当前已经处理好的序列的尾部
        //右指针指向待处理序列的头部
        int n = nums.size(), left = 0, right = 0;
        while(right < n){
            if(nums[right]){
                swap(nums[left], nums[right]);
                left++;
            }
            right++;
        }
    }
};

02 盛最多水的容器

class Solution {
public:
    int maxArea(vector<int>& height) {
        int l = 0, r = height.size() - 1;
        int ans = 0;
        while(l < r){
            int area = min(height[l], height[r])*(r - l); //计算当前水量
            ans = max(ans, area);

            if(height[l] < height[r]) ++l; //移动挡板
            else --r;
        }
        return ans;
    }
};

03 三数之和

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        //排序
        sort(nums.begin(), nums.end());

        vector<vector<int>> ans;
        int n = nums.size();
        for(int first = 0; first < (n - 2); ++first){ //1 first < (n - 2)
            if(first > 0 && nums[first] == nums[first - 1]) continue;
		   
            //双指针
            int third = n - 1;
            int target = -nums[first];
            for(int second = (first + 1); second < (n - 1); ++second){ //2 second < (n - 1)
                if(second > (first + 1) && nums[second] == nums[second - 1]) continue;

                while(second < third && nums[second] + nums[third] > target) --third;
                if(second == third) break;
                if(nums[second] + nums[third] == target){
                    ans.push_back({nums[first], nums[second], nums[third]});
                }
            }
        }
        return ans;
    }
};

04 接雨水

class Solution {
public:
    int trap(vector<int>& height) {
        
    }
};

方法一:哈希数组

  • 建立两个哈希数组,leftMax(n)rightMax(n)

  • leftMax[i] 用来存储 i 左边的最大柱子

  • rightMax[i] 用来存储 i 右边的最大柱子

  • i 的储水值为 min(leftMax[i], rightMax[i]) - height[i]

  • 注:if(n == 0) return 0;

class Solution {
public:
    int trap(vector<int>& height) {
        int n = height.size();
        if(n == 0) return 0;

        vector<int> leftMax(n);
        leftMax[0] = height[0];
        for(int i = 1; i <= n-1; ++i){
            leftMax[i] = max(leftMax[i - 1], height[i]);
        }

        vector<int> rightMax(n);
        rightMax[n - 1] = height[n - 1];
        for(int i = (n - 2); i >= 0; --i){
            rightMax[i] = max(rightMax[i + 1], height[i]);
        }

        int ans = 0;
        for(int i = 0; i < n; ++i){
            ans += min(leftMax[i], rightMax[i]) - height[i];
        }
        return ans;
    }
};

方法二:单调栈

  • 建立一个单调栈 stk,用来存储单调不增长柱子序列

  • 遇到高个柱子,秒掉 top,增加一层雨水

  • 一层雨水体积为 (i - left - 1) * (min(height[left], height[i]) - height[top])

  • 注:if(stk.empty()) break;

class Solution {
public:
    int trap(vector<int>& height) {
        stack<int> stk;
        int n = height.size();
        int ans = 0;

        for(int i=0; i<n; ++i){
            while(!stk.empty() && height[i] > height[stk.top()]){
                int top = stk.top();
                stk.pop();
                if(stk.empty()) break;

                int left = stk.top();
                int currWidth = i - left - 1;
                int currHeight = min(height[left], height[i]) - height[top];
                ans += currHeight * currWidth;
            }
            stk.push(i);
        }
        return ans;
    }
};

方法三:双指针

  • 建立双指针 leftright,用来存储左边最大柱子和右边最大柱子

  • 左边柱子低,则移动 left ,添加一列雨水

  • 右边柱子低,则移动 right ,添加一列雨水

  • 一列雨水体积为 leftMax - height[left]rightMax - height[right]

class Solution {
public:
    int trap(vector<int>& height) {
        int n = height.size();
        int ans = 0;
        int left = 0, right = n - 1; //双指针
        int leftMax = 0, rightMax = 0;
        
        while(left < right){
            leftMax = max(leftMax, height[left]);
            rightMax = max(rightMax, height[right]);
            if(leftMax < rightMax){
                ans += leftMax - height[left];
                ++left;
            }else{
                ans += rightMax - height[right];
                --right;
            }
        }
        return ans;
    }
};

作者:力扣官方题解
链接:https://leetcode.cn/problems/move-zeroes/solutions/489622/yi-dong-ling-by-leetcode-solution/
来源:力扣(LeetCode)

相关文章:

  • 软件工程:软件需求之需求分析方法
  • 知识图谱的推荐实现方案(Vue)
  • 005-Docker 安装 Redis
  • stm32 jlink烧录时写保护
  • Metal学习笔记十一:贴图和材质
  • 算24点
  • C# Equals 和 ReferenceEquals 使用详解
  • Metal学习笔记七:片元函数
  • Spark 介绍
  • AI赋能企业协作4-NL2Sql技术路线
  • Linux 基础---文件权限
  • 数学软件Matlab下载|支持Win+Mac网盘资源分享
  • FPGA学习篇——Verilog学习2
  • 02.02、返回倒数第 k 个节点
  • 3-7 WPS JS宏 工作表移动复制实例-2(多工作簿的多工作表合并)学习笔记
  • 二、Redis 安装与基本配置:全平台安装指南 服务器配置详解
  • 软件工程中的各种图
  • 硅基流动nodejs流式输出
  • 文本挖掘+情感分析+主题建模+K-Meas聚类+词频统计+词云(景区游客评论情感分析)
  • 刚安装docker并启动docker服务: systemctl restart docker报错解决
  • 上市公司重大资产重组新规九要点:引入私募“反向挂钩”,压缩审核流程
  • 白玉兰奖征片综述丨海外剧创作趋势观察:跨界·融变·共生
  • 新修订的《餐饮业促进和经营管理办法》公布,商务部解读
  • 泽连斯基已离开土耳其安卡拉
  • 腾讯一季度净利增14%:AI直接拉动广告收入增长,王者荣耀流水创新高
  • 回望星河深处,唤醒文物记忆——读《发现武王墩》