LeetCode 基础刷题D2

知识点:双向指针盛最多水的容器 接雨水【基础算法精讲 02】_哔哩哔哩_bilibili

相关题目与题解:

  1. 盛最多水的容器
cpp 复制代码
class Solution {
public:
    int maxArea(vector<int>& height) {
        // 思路:面积=宽度*最小高度,优先缩宽度、提高度
        int n = height.size();
        int left = 0;          // 左指针,初始在数组最左端
        int right = n - 1;     // 右指针,初始在数组最右端
        int ans=0, area = 0;     // 【问题1】ans未初始化!会导致随机值,最终结果错误
        while (left < right) { // 指针相遇时停止(宽度为0,无意义)
            // 计算当前指针组合的面积:最小高度 * 指针间距(宽度)
            area = min(height[left], height[right]) * (right - left);
            // 更新最大面积:取当前最大面积和新计算面积的较大值
            ans = max(ans, area); 
            // 核心策略:移动较矮的指针(移动较高指针无法提升最小高度,只会缩宽度)
            if (height[left] < height[right]) {
                left++;
            } else
                right--;
        }
        return ans;
    }
};
  1. 接雨水
cpp 复制代码
class Solution {
public:
    int trap(vector<int>& height) {
        // 边界处理:数组长度<3时无法接水,直接返回0
        //if (height.size() < 3) return 0;
        
        int n = height.size();
        // 初始化前后缀数组大小为n,避免越界
        vector<int> pre_height(n); 
        // 前缀最大值数组:pre_height[i]表示i左侧(含i)的最大高度
        vector<int> pro_height(n);  
        // 后缀最大值数组:pro_height[i]表示i右侧(含i)的最大高度
        
        // 构建前缀最大值数组
        pre_height[0] = height[0];
        for (int i = 1; i < n; i++) {  // 遍历整个数组,而非到n-1
            pre_height[i] = max(height[i], pre_height[i - 1]);
        }
        
        // 构建后缀最大值数组
        pro_height[n - 1] = height[n - 1];
        for (int i = n - 2; i >= 0; i--) {  // 遍历到0,而非>0
            pro_height[i] = max(height[i], pro_height[i + 1]);
        }
        
        int ans = 0;
        // 遍历每个位置(0到n-1),计算每个位置能接的水量
        for (int i = 0; i < n; i++) {
            // 每个位置接水量 = 左右两侧最大高度的较小值 - 当前高度(结果≥0才有效)
            ans += min(pre_height[i], pro_height[i]) - height[i];
        }
        return ans;
    }
};
  1. 验证回文串
cpp 复制代码
class Solution {
public:
    bool isPalindrome(string s) {
        // 将所有大写字符转换为小写字符、并移除所有非字母数字字符之后.
        //! isalnum() 用于判断 "非字母数字字符"
        // 思路:左指针往前走,右指针往后走,遇到非字母数字字符跳过;全转化为小写字母进行判断
        // isalpha()	判断是否是字母	过滤数字 / 符号
        // isdigit()	判断是否是数字	提取数字 / 过滤字母
        // tolower()	转小写字母	忽略大小写比较
        // toupper()	转大写字母	忽略大小写比较
        int n=s.size()-1;
        int left=0; int right=n;
        while(left<right){
            if(!isalnum(s[left])) left++;
            else if(!isalnum(s[right])) right--;
            else if(tolower(s[left])==tolower(s[right])) {
                left++;
                right--;
            }//下面两个都用else if,可以保证每次都只移动一个指针,不会出现移动两个造成指针交叉的情况
            else return false;
        }
        return true;
        
    }
};
  1. 给植物浇水 II
cpp 复制代码
class Solution {
public:
    int minimumRefill(vector<int>& plants, int capacityA, int capacityB) {
        // 直接模拟
        //  capacity先于plants[i]作比较,// 如果<,ans+1,capacity恢复
        // capacity>plants[i],capacity-=plants[i];i++;
        int left = 0;
        int right = plants.size() - 1;
        int ans = 0;
        int cura = capacityA;
        int curb = capacityB;
        while (left < right) {
            //先处理A
            if(cura<plants[left]){
                ans++;
                cura=capacityA;
            }
            cura-=plants[left];
            left++;
            //于此同时B
            if(curb<plants[right]){
                ans++;
                curb=capacityB;
            }
            curb-=plants[right];
            right --;
        }
        if(left==right&&max(cura,curb)<plants[left]){
            ans+=1;
        }
        return ans;
    }
};

复盘与总结

记录错题本

题目一:

cpp 复制代码
int ans, area = 0;     // 【问题1】ans未初始化!会导致随机值,最终结果错误
一开始需要先计算面积大小,然后不断迭代变大。
//面积公式写在前面

题目二:

cpp 复制代码
vector<int> pre_height(n); //声明时长度的写法

       // 构建前缀最大值数组
        pre_height[0] = height[0];
        for (int i = 1; i < n; i++) {  // 遍历整个数组,而非到n-1
            pre_height[i] = max(height[i], pre_height[i - 1]);
        }
第一个的赋值不要忘记!

题目三:

cpp 复制代码
        while(left<right){
            if(!isalnum(s[left])) left++;
            else if(!isalnum(s[right])) right--;
            else if(tolower(s[left])==tolower(s[right])) {
                left++;
                right--;
            }
下面两个都用else if,可以保证每次都只移动一个指针,不会出现移动两个造成指针交叉的情况

题目四:逻辑的整理

代码模板

cpp 复制代码
        int n = height.size();
        int left = 0;          // 左指针,初始在数组最左端
        int right = n - 1;     // 右指针,初始在数组最右端
        int ans = 0;     
        while (left < right){
        这里面也要时刻保证left<right!!
        }
相关推荐
源代码•宸14 小时前
Leetcode—1929. 数组串联&&Q1. 数组串联【简单】
经验分享·后端·算法·leetcode·go
数据大魔方15 小时前
【期货量化实战】跨期套利策略:价差交易完整指南(TqSdk源码详解)
数据库·python·算法·github·程序员创富
weixin_4617694015 小时前
15. 三数之和
c++·算法·leetcode·三数之和
NAGNIP15 小时前
一文搞懂机器学习中的学习理论!
算法·面试
Evand J15 小时前
【MATLAB代码介绍】基于累积概率的三维轨迹匹配与定位,由轨迹匹配和卡尔曼滤波形成算法,带测试结果演示
算法·matlab·滤波·定位·导航·轨迹匹配
l1t15 小时前
NineData第三届数据库编程大赛:用一条 SQL 解数独问题我的参赛程序
数据库·人工智能·sql·算法·postgresql·oracle·数独
千金裘换酒15 小时前
LeetCode 链表两数相加
算法·leetcode·链表
NAGNIP15 小时前
一文搞懂机器学习中的优化方法!
算法
Sammyyyyy15 小时前
Rust 1.92.0 发布:Never Type 进一步稳定
java·算法·rust