枚举算法即遍历已有的集合,判断哪些元素符合要求,最终求解问题。
例如 LeetCode 第一题,两数之和:
1
2
3
4
5
6
7
| 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1]
|
暴力枚举
1
2
3
4
5
6
7
8
9
10
11
12
13
| class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
for (int i = 0; i < nums.size() - 1; i++) {
for (int j = i + 1; j < nums.size(); j++) {
if (nums[i] + nums[j] == target) {
return {i, j};
}
}
}
return { 0, 0 };
}
};
|
时间复杂度:\(O(N^2)\) ,空间复杂度:\(O(1)\)
保留额外信息优化
枚举算法优化技巧:枚举前面的元素时保存已知信息,枚举到后面时利用前面信息直接求解
本题求解 a + b = target 可以转换为 b = target - a ,遍历 a 时在表中查找前面是否出现过对应的 b ,如果出现直接返回,否则将 a 加入表中,供后面的遍历查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> cache;
for (int i = 0; i < nums.size(); i++) {
int a = nums[i];
int b = target - a;
auto iter = cache.find(b);
if (iter != cache.end()) {
return {iter->second, i};
} else {
cache[a] = i;
}
}
return { 0, 0 };
}
};
|
时间复杂度:\(O(n)\) ,空间复杂度 \(O(n)\)
类似例子:
1
2
3
4
5
6
| 设计一个算法,找出数组中两数之和为指定值的所有整数对。一个数只能属于一个数对。
示例 2:
输入:nums = [5,6,5,6], target = 11
输出:[[5,6],[5,6]]
|
同样 a + b = target ,但是存在多对,因此表格中要保存 b 出现的次数,当匹配一次时,次数减 1 ,减到 0 时从表中移除
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| class Solution {
public:
vector<vector<int>> pairSums(vector<int>& nums, int target) {
unordered_map<int, int> cache;
vector<vector<int>> ans;
for (auto num : nums) {
int diff = target - num;
auto iter = cache.find(diff);
if (iter == cache.end()) {
cache[num]++;
} else {
ans.emplace_back(vector<int>{iter->first, num});
iter->second--;
if (iter->second <= 0) {
cache.erase(iter);
}
}
}
return ans;
}
};
|