591 字
3 分钟
算法 : 枚举
2026-04-06

§0.1 枚举右,维护左#

对于 双变量问题,例如两数之和 ai+aj=ta_i + a_j = t,可以枚举右边的 aja_j,转换成 单变量问题,也就是在 aja_j 左边查找是否有 ai=taja_i = t - a_j ,这可以用哈希表维护。

我把这个技巧叫做 枚举右,维护左。 讲解: 1. 两数之和 - 力扣(LeetCode)

class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> idx; // 创建一个空哈希表
for (int j = 0; ; j++) { // 枚举 j
// 在左边找 nums[i],满足 nums[i]+nums[j]=target
auto it = idx.find(target - nums[j]);
if (it != idx.end()) { // 找到了
return {it->second, j}; // 返回两个数的下标
}
idx[nums[j]] = j; // 保存 nums[j] 和 j
}
}
};

§0.2 枚举中间#

对于有三个或者四个变量的问题,枚举中间的变量往往更好算。 为什么?比如问题有三个下标,需要满足 0i<j<k<n0 \le i < j < k < n,对比一下:

  • 枚举 ii,后续计算中还需保证 j<kj < k
  • 枚举 jj,那么 iikk 自动被 jj 隔开,互相独立,后续计算中无需关心 iikk 的位置关系。 所以枚举中间的变量更简单。
class Solution {
public:
int minimumSum(vector<int>& nums) {
int n = nums.size();
vector<int> right(n);
right[n - 1] = nums[n - 1];
for(int i = n - 2; i > 1; i--){
right[i] = min(nums[i], right[i + 1]);
}
int ans = INT_MAX;
int pre = nums[0];
for(int j = 1; j < n - 1; j++){
if(pre < nums[j] && nums[j] > right[j + 1]){
ans = min(ans, pre + nums[j] + right[j + 1]);
}
pre = min(pre, nums[j]);
}
return ans == INT_MAX ? -1 : ans;
}
};
算法 : 枚举
https://dingfengbo.vercel.app/posts/算法/枚举/
作者
Eureka
发布于
2026-04-06
许可协议
CC BY-NC-SA 4.0