枚举右,维护左

参考资料来源灵神在力扣所发的题单,仅供分享学习笔记和记录,无商业用途。

**核心思路:**用一个数据结构维护遍历过的区间,枚举未遍历区间

应用场景:解决双变量问题, 例如两数之和 ai​+aj​=t,可以枚举右边的 aj​,转换成 单变量问题,也就是在 aj​ 左边查找是否有 ai​=t−aj​,这可以用哈希表维护。

**补充:**不会漏掉一个组合,也不会出现重复组合情况

模板:

cpp 复制代码
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> map;
        for(int i=0;i<nums.size();i++){
            //查看维护的区间内是否包含需要的变量
            if(map.find(target-nums[i])!=map.end()) return {map[target-nums[i]],i};
            //更新维护区间
            map[nums[i]]=i;
        }
        return {0,0};
    }
};

力扣题单练习(灵神题单中摘取题目)

2441. 与对应负数同时存在的最大正整数 模板题

cpp 复制代码
class Solution {
public:
    int findMaxK(vector<int>& nums) {
        set<int> s;
        int ret=-1;
        for(int i=0;i<nums.size();i++){
            //维护区间内找到相反数,判断是否为最大正整数
            if(s.find(-nums[i])!=s.end()) ret=max(ret,abs(nums[i]));
            //更新维护区间
            s.insert(nums[i]);
        }
        return ret;
    }
};

121. 买卖股票的最佳时机

**核心思路:**维护左(最小值),枚举右(当前元素-左区间最小值达到当前组合最优结果)。

cpp 复制代码
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        //核心思路:维护左(最小值),枚举右(当前元素-左区间最小值达到当前组合最优结果)。
        int ret=0,buff=INT_MAX;
        for(auto x:prices){
            ret=max(ret,x-buff);
            buff=min(buff,x);
        }
        return ret;
    }
};

624. 数组列表中的最大距离

核心思路:

采用枚举右维护左方式

需要在不同的数组中选取两个数求最大绝对差值。维护前面遍历过的数组最大值和最小值

枚举当前数组中的每一个数从而得出结果

cpp 复制代码
class Solution {
public:
    int maxDistance(vector<vector<int>>& arrays) {
        //核心思路:采用枚举右维护左方式
        //需要在不同的数组中选取两个数求最大绝对差值。维护前面遍历过的数组最大值和最小值
        //枚举当前数组中的每一个数从而得出结果
        sort(arrays.begin(),arrays.end());
        int buff=INT_MAX,full=INT_MIN,ret=0,b,f;
        //维护左初始化第一个数组的最大最小值
        for(int i=0;i<arrays[0].size();i++){
            buff=min(buff,arrays[0][i]);
            full=max(full,arrays[0][i]);
        }
        b=buff;
        f=full;
        for(int i=1;i<arrays.size();i++){
            for(int j=0;j<arrays[i].size();j++){
                //更新结果
                ret=max(ret,abs(arrays[i][j]-buff));
                ret=max(ret,abs(full-arrays[i][j]));
                //更新最小值和最大值
                b=min(b,arrays[i][j]);
                f=max(f,arrays[i][j]);
            }
            //由于选的元素不能在同一个数组中,所以只有遍历完当前数组才能更新最大值和最小值
            buff=b;
            full=f;
        }
        return ret;
    }
};

2364. 统计坏数对的数目

**核心思路:**将j - i != nums[j] - nums[i]转换:nums[j]-j!=nums[i]-i;

**正难反之:**将问题转换成两个数的组合总量-好数对=坏数对,统计nums[j]-j==nums[i]-i数量;

cpp 复制代码
class Solution {
public:
    long long countBadPairs(vector<int>& nums) {
        //核心思路:将j - i != nums[j] - nums[i]转换:nums[j]-j!=nums[i]-i;
        //正难反之:将问题转换成两个数的组合总量-好数对=坏数对,统计nums[j]-j==nums[i]-i数量;
        int n=nums.size();
        unordered_map<int,int> map;
        long long ret=1LL*n*(n-1)/2; //两个数的组合总量,等差公式:(首项+尾项)*累加个数/2
        for(int i=0;i<nums.size();i++) ret-=map[nums[i]-i]++;
        return ret;
    }
};

2905. 找出满足差值条件的下标 II

**核心思路:**枚举右,维护左(采用不定长滑窗维护满足abs(i - j) >= indexDifference的区间)

cpp 复制代码
class Solution {
public:
    vector<int> findIndices(vector<int>& nums, int indexDifference, int valueDifference) {
        //核心思路:枚举右,维护左(采用不定长滑窗维护满足abs(i - j) >= indexDifference的区间)
        int min_buff=0,max_buff=0;
        for(int j=indexDifference;j<nums.size();j++){ //维护abs(i - j) >= indexDifference
            int i=j-indexDifference;
            if(nums[i]>nums[max_buff]){  //维护最大值下标
                max_buff=i;
            }else if(nums[i]<nums[min_buff]){ //维护最小值下标
                min_buff=i;
            }
            //枚举当前元素,在根据维护最大/最小值判断是否满足abs(nums[i] - nums[j]) >= valueDifference
            if(nums[max_buff]-nums[j]>=valueDifference) return {max_buff,j}; 
            if(nums[j]-nums[min_buff]>=valueDifference) return {min_buff,j};
        }
        return {-1,-1};
    }
};

3584. 子序列首尾元素的最大乘积

**核心思路:**枚举右,在子序列为m的前提下,采用不定长滑窗维护从开始~当前位置-m+1的最大/最小值

cpp 复制代码
class Solution {
public:
    long long maximumProduct(vector<int>& nums, int m) {
        //核心思路:枚举右,在子序列为m的前提下,采用不定长滑窗维护从开始~当前位置-m+1的最大/最小值
        long long buff=LLONG_MIN,zz=LLONG_MAX,ret=LLONG_MIN;
        int cnt=0,j=0;
        for(long long x:nums){
            cnt++;
            //当起点~当前元素满足>=m时,维护在起点~当前位置-m+1的最大/最小值
            if(cnt>=m){
                buff=max(buff,(long long)nums[j]);
                zz=min(zz,(long long)nums[j]);
                ret=max(max(ret,zz*x),buff*x);
                j++;  //维护区间尾元素位置
            }
        }
        return ret;
    }
};
相关推荐
智者知已应修善业9 小时前
【51单片机LED闪烁10次数码管显示0-9】2023-12-14
c++·经验分享·笔记·算法·51单片机
智者知已应修善业9 小时前
【51单片机2按键控制1个敞亮LED灯闪烁和熄灭】2023-11-3
c++·经验分享·笔记·算法·51单片机
AI算法沐枫9 小时前
大模型 | 大模型之机器学习基本理论
人工智能·python·神经网络·学习·算法·机器学习·计算机视觉
吃着火锅x唱着歌9 小时前
LeetCode 1019.链表中的下一个更大节点
算法·leetcode·链表
凌波粒9 小时前
LeetCode--404.左叶子之和(二叉树)
算法·leetcode·职场和发展
paeamecium10 小时前
【PAT甲级真题】- A+B in Hogwarts
c++·算法·pat考试·pat
青山师10 小时前
二叉树与BST深度解析:遍历算法与平衡策略
数据结构·算法·面试·二叉树·算法与数据结构·java面试·数据结构与算法分析
绝知此事10 小时前
【算法突围 03】核心算法思想:分治/递归/动态规划与 LeetCode 高频真题解析
算法·leetcode·面试·动态规划
AI科技星10 小时前
第二章 平行素数对网格:矩形→等腰梯形拓扑变换(完整公理终稿)
c语言·开发语言·线性代数·算法·量子计算·agi