所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。
题目
有人相爱,有人夜里开车看海,有人leetcode第一题都做不出来。今天把LeetCode第一题做了一下发现自己编程还存在很多问题。下面我们看一下这道题:
一、暴力穷举法
简单来讲,这道题就是计算数组中两数和,然后判断是否等于目标值。因为在数组中的任意两个数都有可能是结果,最先想到是用两个for循环来遍历,即暴力穷举法。那么我们就得到的如下代码(不一定是最短最优的):
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
for (int i = 0; i < size(nums); i++) {
for (int j = i + 1; j < size(nums); j++) {
if (target == nums[j] + nums[i]) return { i,j };
}
}
return {};
}
};
复杂度分析:
- 时间复杂度: O ( n 2 ) O(n^2) O(n2),最坏的情况下是每个数都要遍历一遍,两个for循环,因此是n平方。
- 空间复杂度: O ( 1 ) O(1) O(1), 开辟了一个vector空间,是一个常量。
二、哈希表法
数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set 也不能用。此时就要选择另一种数据结构:map ,map是一种key value的存储结构,可以用key保存数值,用value在保存数值所在的下标。
这道题目中并不需要key有序,选择unordered_map 效率更高。在遍历数组时我们在map找target - nums[i],找到就退出循环。没找到就保留nums[i]的值,作为下一次循环的map元素。
class Solution {
public:
vector<int> twoSum1(vector<int>& nums, int target) {
unordered_map <int, int> map;
for (int i = 0; i < nums.size(); i++) {
auto iter = map.find(target - nums[i]);
if (iter != map.end()) {
return { iter->second, i };
}
map.insert(pair<int, int>(nums[i], i));
}
return {};
}
};
复杂度分析:
- 时间复杂度: O ( n ) O(n) O(n),最坏的情况下是每个数都要遍历一遍,unordered_map查询只需要 O ( 1 ) O(1) O(1)。
- 空间复杂度: O ( n ) O(n) O(n), map需要的空间为 O ( n ) O(n) O(n)。
完整代码
# include <iostream>
# include <vector>
# include <unordered_map>
using namespace std;
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
for (int i = 0; i < size(nums); i++) {
for (int j = i + 1; j < size(nums); j++) {
if (target == nums[j] + nums[i]) return { i,j };
}
}
return {};
}
vector<int> twoSum1(vector<int>& nums, int target) {
unordered_map <int, int> map;
for (int i = 0; i < nums.size(); i++) {
auto iter = map.find(target - nums[i]);
if (iter != map.end()) {
return { iter->second, i };
}
map.insert(pair<int, int>(nums[i], i));
}
return {};
}
};
void my_print(vector <int>& v, string msg)
{
cout << msg << endl;
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
int arr[] = { 3,3 };
int target = 6;
int len = sizeof(arr) / sizeof(int);
vector<int>nums;
Solution s1;
for (int i = 0; i < len; i++) {
nums.push_back(arr[i]); // 向容器中插入数据
}
my_print(nums, "nums数组:");
vector<int> v = s1.twoSum(nums, target);
my_print(v, "两数之和索引:");
system("pause");
return 0;
}
end