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!!
        }
相关推荐
雾喔24 分钟前
近日总结 & 面试经验
面试·职场和发展
tangguofeng33 分钟前
基于分治策略的循环赛日程表问题的思路讲解
算法
起个名字费劲死了1 小时前
VisionMaster集成深度学习算法(基础狗)
人工智能·深度学习·算法
lengxuenong1 小时前
枚举例题分析
c++·算法·青少年编程
bksczm1 小时前
0基础面试2
网络·面试·职场和发展
Navigator_Z1 小时前
LeetCode //C - 1269. Number of Ways to Stay in the Same Place After Some Steps
c语言·算法·leetcode
2601_965742221 小时前
短视频脚本创作方法分享:本地生活类账号的起步思路
大数据·人工智能·算法·ai·新媒体运营·生活
55873生态系统手记1 小时前
读完 55873 资产钱包的技术栈,我重新理解了 "合规钱包" 应该长什么样
算法·架构
旋生万物2 小时前
素数螺旋映射 $z_n=n^{1+i}$ 的角分布统计检验与零模型对比
大数据·前端·人工智能·算法·云原生·螺旋生成论·螺旋相位
HRTOS2 小时前
HRTOS Shell继续完善:优化printf缓冲区与字符串越界保护,国庆后随新版本更新
运维·单片机·嵌入式硬件·算法·51单片机