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!!
        }
相关推荐
海清河晏1112 小时前
数据结构 | 单循环链表
数据结构·算法·链表
wuweijianlove6 小时前
算法性能的渐近与非渐近行为对比的技术4
算法
_dindong6 小时前
cf1091div2 C.Grid Covering(数论)
c++·算法
AI成长日志6 小时前
【Agentic RL】1.1 什么是Agentic RL:从传统RL到智能体学习
人工智能·学习·算法
黎阳之光7 小时前
黎阳之光:视频孪生领跑者,铸就中国数字科技全球竞争力
大数据·人工智能·算法·安全·数字孪生
skywalker_117 小时前
力扣hot100-3(最长连续序列),4(移动零)
数据结构·算法·leetcode
6Hzlia7 小时前
【Hot 100 刷题计划】 LeetCode 17. 电话号码的字母组合 | C++ 回溯算法经典模板
c++·算法·leetcode
wfbcg7 小时前
每日算法练习:LeetCode 209. 长度最小的子数组 ✅
算法·leetcode·职场和发展
_日拱一卒8 小时前
LeetCode:除了自身以外数组的乘积
数据结构·算法·leetcode
计算机安禾8 小时前
【数据结构与算法】第36篇:排序大总结:稳定性、时间复杂度与适用场景
c语言·数据结构·c++·算法·链表·线性回归·visual studio