枚举右,维护左

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

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

应用场景:解决双变量问题, 例如两数之和 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;
    }
};
相关推荐
ZLRRLZ6 分钟前
【数据结构】二叉树进阶算法题
数据结构·c++·算法
1白天的黑夜131 分钟前
二分查找-153-寻找旋转排序数组中的最小值-力扣(LeetCode)
c++·leetcode·二分查找
pimkle1 小时前
LC 135 分发糖果 JavaScript ts
leetcode·typescript
arin8761 小时前
【图论】倍增与lca
算法·图论
CoovallyAIHub1 小时前
别卷单模态了!YOLO+多模态 才是未来场景实战的“天选方案”
深度学习·算法·计算机视觉
guozhetao2 小时前
【图论,拓扑排序】P1347 排序
数据结构·c++·python·算法·leetcode·图论·1024程序员节
慕雪_mx2 小时前
最短路算法
算法
AI_Keymaker2 小时前
对话DeepMind创始人Hassabis:AGI、宇宙模拟与人类文明的下一个十年
算法
yi.Ist2 小时前
关于二进制的规律
算法·二进制·bitset
88号技师3 小时前
2025年7月一区SCI-投影迭代优化算法Projection Iterative Methods-附Matlab免费代码
开发语言·人工智能·算法·机器学习·matlab·优化算法