一、题目介绍

1.题目描述

->给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值的那两个整数,并返回它们的数组下标。

->你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

->你可以按任意顺序返回答案。

2.题目提示

->2 <= nums.length <= 103

->-109 <= nums[i] <= 109

->-109 <= target <= 109

->只会存在一个有效答案

3.演示案例

输入:nums = [2,7,11,15], target = 9

输出:[0,1]

解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

输入:nums = [3,3], target = 6

输出:[0,1]


二、题目分析

1.输入输出分析

整数数组nums 整数目标值target ---------->符合条件整数的下标组成的数组

2.要求分析

->由于题目描述中可以按任意顺序返回答案,所以[0,1]与[1,0]等价。

->同一元素不能用两次:数组中可能含有重复的数字,但是这些重复的数字的下标不同,所以他们属于不同的元素,这点得注意,如演示实例二。

->题目假设答案唯一,也就是说不需要找到所有的答案,只要找到一个答案就可以输出,如果写了一个函数已经找出了答案,还往下寻找,就会增加程序的执行时间。


三、解法一:穷举式寻找

1.算法理解

->穷举算法适用于所有寻找类型的问题,自己体会一下穷举在下面应用场景的不同之处:

场景1:老师让你从一年级一班里找出一个年龄在7岁以上的同学。

场景2:老师让你从一年级一班里找出所有年龄在7岁以上的同学。

场景3:老师让你从一年级一班里找出两个年龄和为15岁的两个人,用来参加这次的二人乒乓比赛。

场景4:老师让你从一年级一班里找出两个年龄和为15岁的两个人的所有配对方式,然后通过综合筛选出一对,用来参加这次的二人乒乓比赛。

->可以看见,穷举的基本过程可以描述为:对目标群体进行遍历,对于遍历所得到的目标进行筛选判断,进而筛选出满足条件的目标。

要注意的是,其中的遍历,可以根据目标群体的类型,分为一次遍历,二次遍历等等,要明白,遍历的目的只是为了得到可以用来被判断的目标。

->显然本题的场景跟场景3是相似的。

2.C++语法基础

2.1数组

->原谅我python看习惯了,竟然一开始下意识把C++的数组的括号用成了中括号,写成了int arr =[1,2,3],真是一点都不会C++啊。。。

->好像Leecode的数组用的都是vector,就是一个可以存放任何类型数据的一个动态数组,并且这个动态数组还有一些函数可以使用,如以下函数:

pop_back() //用于删除动态数组的最后一个元素。

push_back() //用于在动态数组尾部添加新的值。

empty() //用于判断数组是否为空,如果为空返回1;反之返回0。

size() //用于返回数组中元素的个数。

->创建容器方式

#include <vector>  //Leecode里自带C++的标准库,不需要导入。
vector<type>var;

2.2&与*

->*后跟指针型变量表示该指针所对应的数值,如int *p

->&后跟非指针型变量表示该变量的地址,如 p =&var

->一个脑残的代码示范:

int *p;
int a =100;
int b =200;
&a =&b; //这行是错误的,对于一个变量来说,变量值是可以修改的,但是变量的地址是不能修改的。
p =&b; /**这行是正确的,p虽然表示的是内存地址,但是它所表示的内存地址就是它这个指针型变量对应的值是没有问题的,指针只是一个特殊的变
量,它也有自己的内存地址,只不过它所对应的值刚好也是内存地址。**/
&p =&b; //这一行也是错误的,因为指针变量的地址不可以被修改,任何变量的地址都不能被修改。

->C++中&的另一个作用----引用

声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元,这就是为什么函数里的参数多是引用,可以节省空间的开销,还可以直接通过形参的改变进而改变实参,如

void swap(int &p1, int &p2) //此处函数的形参p1, p2都是引用
{ int p; p=p1; p1=p2; p2=p; }

3.我的题解

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 {};
}
};

四、解法二:利用哈希表优化穷举的时间开销

1.算法理解

->本质上还是穷举的思路,但是在寻找的过程中,通过哈希表的数据结构将查找时间O(n)变成了O(1)。因为正常情况下从一个数组中找到自己想要找到所有的元素需要对数组里的所有元素都进行一次判断,但是从哈希表中找到一个自己想要的元素,直接就找到了,因为哈希表中所有元素的地址都是通过哈希算法根据元素名算出来的,也就是说增加了存储消耗,但是优化了查找效率。

->对于循环遍历的理解:

正常情况下,我们对一个数组的遍历是array[0],array[1],array[2],array[3].....

我们也可以反向遍历array[n-1],array[n-2],array[n-3],array[n-4]....其中n为数组中元素的个数

所以一个二次遍历共有四种遍历方式:

第一次从起点正向遍历,第二次从第一次循环的初始点正向遍历。

第一次从起点正向遍历,第二次从第一次循环的初始点反向遍历。

第一次从末尾反向遍历,第二次从第一次循环的初始点正向遍历。

第一次从末尾反向遍历,第二次从第一次循环的初始点反向遍历。

这有什么好处呢?在特殊情况下,可以减少代码的编写量。

->这里我的算法思路是

第一次从起点正向遍历,代码如下:

for(int i=0;i<nums.size();i++){code}

第二次从初始点反向遍历,代码如下:

for(int s=i-1;i>=0;i--){code}   //因为题目中同一个元素不能跟自己所匹配,所以起点从i往左移动一个位置,使之跟自己前面的所有元素进行累加确定值是否为target

把上面的二次遍历优化为哈希表,索引为i的元素跟自己之前的所有元素进行匹配可以看做是跟哈希表进行匹配,每一次迭代中,如果哈希表找不到元素,就将哈希表向右边扩充一个pair,代码如下:

auto ii =hashmap.find(target-nums[i]); //这里auto是C++11新标准,申明变量后自动确定该变量对应的类型。
if(ii!=hashmap.end()){
return {i,ii->second};
}
hashmap.insert(make_pair(nums[i],i));

2.C++算法基础

2.1C++ 中的 ::

https://blog.csdn.net/qq1623803207/article/details/89398435

2.2C++ 中的unordered_map

->首先说一下,C++11在std中定义了很多容器,这些容器的效率非常高,根本没有必要自己去定义数据结构,这里的unordered_map就是一种类似于哈希表的容器,它的作用就是优化查找效率,而vector容器的作用就相当于于动态数组,我真的是爱死C++了,本来以为C++中的库很垃圾,跟python根本没法比,但是现在才发现C++真的十分优美,高效,简洁。这里unordered_map的头文件为<unordered_map>,注意跟vector容器一样,在leecode里这些头文件都默认已经有过了。

->unordered_map的迭代器是一个指针,指向这个元素,通过迭代器来取得它的值,就相当于数组里的索引i一样,初始迭代器就是i=0,末尾迭代器就是i=array.size()。

1 it->first;               // same as (*it).first   (the key value)
2 it->second; // same as (*it).second (the mapped value)

->成员函数

begin    返回指向容器起始位置的迭代器

end    返回指向容器末尾位置的迭代器 ,该迭代器指向unordered_map容器中最后一个元素之后的位置

size    返回有效元素个数

empty 判断是否为空,如果为空;返回1,非空返回0

find 如果key存在,则find返回key对应的迭代器,如果key不存在,则find返回unordered_map::end。可以通过map.find(key) == map.end()来确定key是否存在于unordered_map中。

insert 插入键值对,至于如何获得键值对,可以使用std::make_pair函数获得。

3.我的题解

class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int> hashmap;
for(int i=0;i<nums.size();++i){
auto ii =hashmap.find(target-nums[i]);
if(ii!=hashmap.end()){
return {ii->second,i};
}
hashmap.insert(make_pair(nums[i],i));
}
return {}; }
};

最新文章

  1. iOS开发之功能模块--计算高度Demo探究手稿
  2. iPad开发--美团界面的搭建(主要是对Popover的使用,以及监听)
  3. 深入探索AngularJS(持续更新)
  4. svn转移版本库
  5. WAMP Server助你在Windows上快速搭建PHP集成环境
  6. hdu 2177 取(2堆)石子游戏 博弈论
  7. Trainning Guide, Data Structures, Example
  8. leetcode reverse integer&amp;&amp;Palindrome Number
  9. SPOJ-COT-Count on a tree(树上路径第K小,可持久化线段树)
  10. Unity3D基础学习之AssetBundle 资源包创建与加载
  11. Unity之GUI控件
  12. BZOJ 1724: [Usaco2006 Nov]Fence Repair 切割木板
  13. Apache 与tomcat区别
  14. IT行业有前景么?一个10年行内人的6点看法
  15. 201521123010 《Java程序设计》第13周学习总结
  16. APK安装成功后点击&quot;打开&quot;,按Home键,在桌面点击图标后应用重启
  17. (转!)利用Keras实现图像分类与颜色分类
  18. BlockTrain网络
  19. 《Linux 性能及调优指南》1.4 硬盘I/O子系统
  20. Oracle DUL/AUL/ODU 工具说明

热门文章

  1. Codeforces Round #739 (Div. 3)
  2. 【然天一】随机读写(4k)百盘天梯
  3. ApacheCN 数据科学译文集 20211109 更新ApacheCN 数据科学译文集 20211109 更新
  4. Visual Studio 2010 怎么查看函数的重载数量、范围、种类等
  5. 数论同余学习笔记 Part 2
  6. Swift中类的使用
  7. HTTPS的基本使用
  8. 报错:java.sql.SQLException: Value '0000-00-00 00:00:00' can not be represented as java.sql.Timestamp
  9. insert/delete/select/update 以及一些在select中常用的函数之类的
  10. LeetCode随缘刷题之截断句子