参考资料来源灵神在力扣所发的题单,仅供分享学习笔记和记录,无商业用途。
**核心思路:**用一个数据结构维护遍历过的区间,枚举未遍历区间
应用场景:解决双变量问题, 例如两数之和 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};
}
};
力扣题单练习(灵神题单中摘取题目)
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;
}
};
**核心思路:**维护左(最小值),枚举右(当前元素-左区间最小值达到当前组合最优结果)。
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;
}
};
核心思路:
采用枚举右维护左方式
需要在不同的数组中选取两个数求最大绝对差值。维护前面遍历过的数组最大值和最小值
枚举当前数组中的每一个数从而得出结果
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;
}
};
**核心思路:**将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;
}
};
**核心思路:**枚举右,维护左(采用不定长滑窗维护满足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};
}
};
**核心思路:**枚举右,在子序列为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;
}
};