一、题目介绍

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

C++_Leecode1 两数之和的更多相关文章

  1. 给定数组A,大小为n,现给定数X,判断A中是否存在两数之和等于X

    题目:给定数组A,大小为n,现给定数X,判断A中是否存在两数之和等于X 思路一: 1,先采用归并排序对这个数组排序, 2,然后寻找相邻<k,i>的两数之和sum,找到恰好sum>x的 ...

  2. LeetCode 170. Two Sum III - Data structure design (两数之和之三 - 数据结构设计)$

    Design and implement a TwoSum class. It should support the following operations: add and find. add - ...

  3. LeetCode 371. Sum of Two Integers (两数之和)

    Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -. Exam ...

  4. LeetCode 167. Two Sum II - Input array is sorted (两数之和之二 - 输入的是有序数组)

    Given an array of integers that is already sorted in ascending order, find two numbers such that the ...

  5. [LeetCode] Two Sum IV - Input is a BST 两数之和之四 - 输入是二叉搜索树

    Given a Binary Search Tree and a target number, return true if there exist two elements in the BST s ...

  6. [LeetCode] 1. Two Sum 两数之和

    Part 1. 题目描述 (easy) Given an array of integers, return indices of the two numbers such that they add ...

  7. Leetcode(一)两数之和

    1.两数之和 题目要求: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重 ...

  8. 南大算法设计与分析课程OJ答案代码(1)中位数附近2k+1个数、任意两数之和是否等于给定数

    问题1 用来测试的,就不说了 问题2:中位数附近2k+1个数 给出一串整型数 a1,a2,...,an 以及一个较小的常数 k,找出这串数的中位数 m 和最接近 m 的小于等于 m 的 k 个数,以及 ...

  9. 两数之和,两数相加(leetcode)

    我们都知道算法是程序员成长重要的一环,怎么才能提高算法呢, 出来在网上看视频之外,动手练习是非常重要的.leetcode 就是一个非常好的锻炼平台. 1. 两数之和,在 leetcode 里面是属于 ...

随机推荐

  1. python 小兵面向对象

    Python 面向对象 Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的.本章节我们将详细介绍Python的面向对象编程. 如果你以前没有接触过 ...

  2. 如何在pyqt中在实现无边框窗口的同时保留Windows窗口动画效果(一)

    无边框窗体的实现思路 在pyqt中只要 self.setWindowFlags(Qt.FramelessWindowHint) 就可以实现边框的去除,但是没了标题栏也意味着窗口大小无法改变.窗口无法拖 ...

  3. AT2347 [ARC070C] NarrowRectangles

    首先不难看出一个暴力的 \(dp\) 解法,考虑令 \(dp_{i, j}\) 表示考虑完前 \(i\) 个矩形,第 \(i\) 个矩形左端点在 \(j\) 时所需要的最小花费. 不难有转移: \[d ...

  4. 分子动力学模拟之基于自动微分的LINCS约束

    技术背景 在分子动力学模拟的过程中,考虑到运动过程实际上是遵守牛顿第二定律的.而牛顿第二定律告诉我们,粒子的动力学过程仅跟受到的力场有关系,但是在模拟的过程中,有一些参量我们是不希望他们被更新或者改变 ...

  5. 宝塔面板部署springboot项目并使用域名访问

    环境准备:服务器搭建宝塔linux面板项目: springboot项目项目打包方式jar包 环境: 一.服务器,一个域名,然后再服务器上(DNS服务)将域名解析好.把安全组设置好. 二.用宝塔快速搭建 ...

  6. 对常用I/O模型进行比较说明

    一.IO模型的四个特性 关注的是消息通信机制,即调用者在等待一件事情的处理结果时,被调用者是否提供完成状态的通知. 同步:synchronous,被调用者并不提供事件的处理结果相关的通知消息,需要调用 ...

  7. [翻译]Introduction to JSON Web Tokens

    JWT: Json Web Tokens JWT是一种开放标准(RFC 7519),它定义了一种紧凑且独立的方式,用于将各方之间的信息安全地传输为JSON对象.因为它是经过数字签名的,所以该信息可以进 ...

  8. B快速导航

    GETTING STARTED If you are new to Selenium, we have a few resources that can help you get up to spee ...

  9. PL/SQL批量执行SQL脚本文件

    1.选择File > New > Command Windows(命令窗口) 2.输入 @ 符号,之后敲击回车键.从本地选择执行的 SQL脚本 等待批量命令全部执行成功,关闭页面即可 新增 ...

  10. 如何写出优雅又地道的Python代码?【转载】

    在Python社区文化的浇灌下,演化出了一种独特的代码风格,去指导如何正确地使用Python,这就是常说的pythonic.一般说地道(idiomatic)的python代码,就是指这份代码很pyth ...