枚举右,维护左

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

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

应用场景:解决双变量问题, 例如两数之和 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;
    }
};
相关推荐
喵手10 分钟前
Python爬虫实战:电商实体消歧完整实战 - 从混乱店铺名到标准化知识库的工程化实现,一文带你搞定!
爬虫·python·算法·爬虫实战·零基础python爬虫教学·同名实体消除·从混乱店铺名到标准化知识库
weixin_4521595514 分钟前
C++与Java性能对比
开发语言·c++·算法
80530单词突击赢14 分钟前
C++哈希表实现:开散列与闭散列详解
算法·哈希算法·散列表
Timmylyx051817 分钟前
类欧几里得学习笔记
笔记·学习·算法
wangluoqi20 分钟前
26.2.2练习总结
算法
2301_7657031421 分钟前
C++中的工厂模式实战
开发语言·c++·算法
鱼跃鹰飞22 分钟前
Leetcode:97.交错字符串
linux·服务器·leetcode
星火开发设计1 小时前
C++ 输入输出流:cin 与 cout 的基础用法
java·开发语言·c++·学习·算法·编程·知识
We་ct1 小时前
LeetCode 289. 生命游戏:题解+优化,从基础到原地最优
前端·算法·leetcode·矩阵·typescript
自己的九又四分之三站台1 小时前
9:MemNet记忆层使用,实现大模型对话上下文记忆
人工智能·算法·机器学习