讲解LeetCode第1题:两数之和(完整代码)
题目介绍:
输入:nums={2,7,11,15} , target=22
输出:1,3
解释:因为num[1]+num[3]==22 , 所以返回1,3
方法一:暴力枚举
完整代码展示
#include<iostream>
#include<vector>
using namespace std;
class Solution
{
public:
vector<int>twoSum(vector<int>&nums, int target)
{
int n = nums.size();
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
if (nums[i] + nums[j] == target)
{
return{ i,j };
}
}
}
return {};
}
};
int main()
{
vector<int>nums = { 2,7,11,15 };
int target = 22;
Solution find;
vector<int>result=find.twoSum(nums, target);
if (!result.empty())
{
cout << "目标值" << target << "是下标为"
<< result[0] << "和" << result[1]
<< "对应的值之和" << endl;
}
else
{
cout << "没有两数之和是" << target << endl;
}
return 0;
}
核心原理演示
输入:nums={2,7,11,15} , target=22
输出:1,3
代码片段解释
片段一:
#include<iostream>
#include<vector>
iostream库是C++标准库的一个头文件,他提供了进行输入和输出操作的类。例如:输入类
istream
和输出类ostream
。我们在C++使用的cin和cout就是这些类的实例化对象。vector容器类是C++标准模板库 (STL)的一个头文件,它提供了一种能够存储任意类型的动态数组的容器。
总而言之:这两行代码通过包含C++标准库中的iostream和vector头文件,使得你的程序能够使用
输入输出流
和动态数组
的功能。
注:与C语言中的数组不同,vector的大小可以在运行时改变,他会自动管理其存储的内存。
片段二:
return{ i,j };
return {};
这两句代码使用了C++11引入的
列表初始化
语法:它允许你直接在返回语句中初始化一个对象。例如:return{i,j};中就创建一个临时vector对象,并用i和j作为它的初始化元素。
即,在C++11中,当你使用花括号{}包围一系列值时,并且这些值被用于需要特定类型对象的上下文中(比如函数的返回类型),编译器会自动进行
类型推导
和对象初始化
。
片段三:
int n = nums.size();
if (!result.empty())
这两句代码中nums和result都是vector容器类实例化的对象,这里这两个对象分别调用了不同的成员函数。
成员函数size(), 该函数返回容器中元素的数量。
成员函数empty(), 该函数返回一个布尔值,判断容器是否为空。如果为空返回true,否则返回false。
注:这两个成员函数不仅适用于vector容器,还适用于list容器。
方法二:哈希表
完整代码展示
#include<iostream>
#include<vector>
#include<unordered_map>
using namespace std;
class Solution
{
public:
vector<int>twoSum(vector<int>&nums, int target)
{
unordered_map<int, int>hashtable;
for (int i = 0; i < nums.size(); i++)
{
auto it = hashtable.find(target - nums[i]);
if (it != hashtable.end())
{
return { it->second,i };
}
hashtable[nums[i]] = i;
}
return{};
}
};
int main()
{
vector<int>nums = { 6,3,8,2,1 };
int target = 8;
Solution find;
vector<int>result = find.twoSum(nums, target);
if (!result.empty())
{
cout << "目标值" << target << "是下标为"
<< result[0] << "和" << result[1]
<< "对应的值之和" << endl;
}
else
{
cout << "没有两数之和是" << target << endl;
}
return 0;
}
核心原理演示
输入:nums={6,3,8,2,1} , target=8
输出:0,3
代码片段解释
片段一:
#include<unordered_map>
unordered_map<int, int>hashtable;
与vector同样unordered_map也是C++标准模板库的一个头文件。
vector定义了一个
序列容器
,unordered_map定义了一个关联容器
。unorder_map存储的元素是键值对(key-value pairs),其中每一个键都是唯一的,并且映射到一个值。
因此
unordered_map<int, int>hashtable;
创建了一个unorder_map<int,int>类型的关联容器hashtable,用以存储数组nums中的元素值作为键(key),以及这些元素在数组中的索引作为值(value)。
片段二:
auto it = hashtable.find(target - nums[i]);
if (it != hashtable.end())
这两句代码中hashtable分别调用了unordered_map的两个成员函数。
成员函数find()
:该函数返回一个找到的键
的迭代器,作为查找键
的最终结果。
- 如果找到了对应的
键
(本例中是target - nums[i]),迭代器将指向该键对应的元素- 如果没有找到,迭代器将等于一个特殊的迭代器end()
成员函数end()
:该函数返回一个特殊的迭代器,它指向容器的“尾部位置”。
(注:这不是一个有效的元素位置,而是用作算法和成员函数的一个终止条件),所以说任何指向容器内元素的迭代器都会小于end()迭代器。
片段三:
return { it->second,i };
it->second用于访问迭代器it指向的元素的
键
相关联的值
。或者可以理解为通过it->second访问迭代器it指向的元素的值
部分。
片段四:
hashtable[nums[i]] = i;
这行代码是在向一个名为hashtable的unorder_map容器中
添加
或更新
一个键值对。
- 键:nums[i],是正在遍历的nums数组中的元素。
- 值:i,是该元素在nums数组中的索引。
注意:
如果hashtable中不存在键等于nums[i],那么一个新的键值对将被
添加
到hashtable中,键为nums[i],值为i。如果hashtable中已经存在一个键等于nums[i],那么它相关联的值将被
更新
为当前的i