题目:
给定一个整数数组
nums
和一个整数目标值target
,请你在该数组中找出 和为目标值target
的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9 输出:[0,1] 解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。示例 2:
输入:nums = [3,2,4], target = 6 输出:[1,2]示例 3:
输入:nums = [3,3], target = 6 输出:[0,1]提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
- 只会存在一个有效答案
进阶:你可以想出一个时间复杂度小于
O(n2)
的算法吗?
小菜汪的解题思路(暴力求解)
输入:nums数组、target目标
输出:两数相加等于target的下标值
1. 设置answer存储返回值答案的向量,因为题目返回值是vector<int>
2. 用len获取输入数组的长度
3. 用两个for循环找到相加为target的两个数
a. 若有,将其下标放入answer向量
b. 若全部扫描没有,返回空的answer向量
4.返回answer向量
时间复杂度为:
空间复杂度:
空间复杂度也不是用来计算程序实际占用的空间的,而是对一个算法在运行过程中临时占用存储空间大小的一个量度。这个地方我用了一个answer向量,感觉他是随着n变化的,不知道应该是还是,有会的友友可以帮我解答一下。
(130条消息) 时间复杂度和空间复杂度的计算!!_犬冢紬希的博客-CSDN博客_如何计算时间和空间复杂度
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int>answer; //设置一个存储答案的向量answer 因为返回值是vector
int len=nums.size(); // 获取输入数组的长度
for(int i=0;i<len;i++) // 第一个for作为第一个数
{
for(int j=i+1;j<len;j++) //确定第一个数之后,数组向后扫描第二个数
{
if(nums[i]+nums[j]==target)// 如果第一个数和第二个数之和为target
{
answer.push_back(i); //把第一个数小标放进答案
answer.push_back(j); //把第二个数下标放进答案
return answer; // 返回答案向量
}
}
}
return answer; //返回答案向量
}
};
官方思路1——暴力求解:
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 {};
}
};
作者:力扣官方题解
链接:https://leetcode.cn/problems/two-sum/solutions/434597/liang-shu-zhi-he-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
对比:思路相同,但是他没有设置返回的向量,直接返回的是{i,j}和{}
方法一问题&总结:
1. 为什么返回的是{i,j}、{},返回值不应该是vector<int>类型的吗?
答:vector实际上是一个动态数组。数组的初始化方式有四种如下,也是用{ }赋值的。vector赋值方式也是用{ },所以可以直接返回{}(代表返回向量为空),{i,j}(只返回这个,是因为题目说了答案只有一个,可以直接返回)
数组的四种赋值方式:
//1. 直接给每个元素赋值
int array1[4] = {1,2,3,4};
//2. 给一部分赋值,后面的全部为0
int array2[4] = {1,2};
//3. 由赋值参数个数决定数组的个数
int array3[] = {1,2};
//4. 数组元素的值是随机分配的
int array4[4] = {};
vector的赋值方式:
// 1.直接赋值
vector<int> arr = { 1, 2, 3 };
// 2.初始化为空的vector,此时size为0
vector<int> arr;
————————————————
版权声明:本文为CSDN博主「giantmfc123」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/mafucun1988/article/details/89547503
官方思路2——哈希表
解题思路:
输入:nums数组、target目标
输出:两数相加等于target的下标值
步骤:(以官方视频为例)
(1)设置数组长度变量len,建立哈希表hastable(key:nums中的数,value:该数的下标
(2) 一层for循环,选择第一个数,则第二个数=target-第一个数
设置迭代器 it(类似指针)在哈希表里面找 find,有没有第二个数的值 target-nums[i] ?
a. 若有,则返回 it->second(即为哈希表的value值,为第二个数下标)
b. 若没有,则将 第一个数的值作为key,下标作为value,放入哈希表中,以便下次查找。
(意思就是说:比如说第一次数6,没有找到2,但是这个时候把6存下来,后面数组中出现了2,就可以很快找到6的下标了)
时间复杂度: (只有一次for循环)
空间复杂度: (因为有了哈希表,他动态变化的,和n有关)
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int len=nums.size(); //获取输入nums长度
unordered_map<int,int>hastable; //建立哈希表hastable
for(int i=0;i<len;i++){
auto it = hastable.find(target-nums[i]); //auto是关键字 it是迭代指针
if(it!=hastable.end()) //如果it没有到了哈希表最后,说明找到了第二个数相加为target
{
return {it->second,i}; //返回it的value值,即第二数的下标
}
hastable[nums[i]]=i;
//如果it到了哈希表最后都没找到,那么把第一个数存入哈希表,希望后面第二个数能与之匹配
}
return {}; //所有数扫描结束都没找,就返回空的{}
}
};
方法二问题&总结:
1.什么是哈希表
答: “散列表(Hash table,也叫哈希表),是根据键(Key)而直接访问在内存存储位置的数据结构。也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表。
简而言之,哈希表类似于键值对表。
(134条消息) C++ 哈希表_ZS_Wang_Blogs的博客-CSDN博客_c++哈希表是什么
2.为什么用哈希表
(1) 一般哈希表都是用来快速判断一个元素是否出现在集合里。
(2) 可以根据一个key值来直接访问数据,因此查找速度快
3.auto的含义?
auto是c++程序设计语言的关键字。用于两种情况
(1)声明变量时根据初始化表达式自动推断该变量的类型(该题属于第一种)
(2)声明函数时函数返回值的占位符
auto可以在声明变量时根据变量初始值的类型自动为此变量选择匹配的类型。
举例:对于值x=1;既可以声明: int x=1 或 long x=1,也可以直接声明 auto x=1
(134条消息) c++ auto类型用法总结_小拳头的博客-CSDN博客_auto是什么意思
4.哈希表的使用