一、题目介绍

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. TypeScript入门文档

    typescript入门文档链接d地址:https://ts.xcatliu.com/basics/type-of-function.html 博主个人站点:www.devloper.top

  2. Spring源码-IOC部分-Spring是如何解决Bean循环依赖的【6】

    实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] Spring ...

  3. Java向mysql中插入时间的方法

    ava向MySQL插入当前时间的四种方式和java时间日期格式化的几种方法(案例说明);部分资料参考网络资源  java向MySQL插入当前时间的四种方式 第一种:将java.util.Date类型的 ...

  4. Python--变量和简单数据类型

    Python--变量和简单数据类型 目录 Python--变量和简单数据类型 一.Python脚本运行过程 二.变量 1. 变量的命名和使用 2. Python关键字和内置函数 2.1 Python关 ...

  5. 这个Dubbo注册中心扩展,有点意思!

    今天想和大家聊聊Dubbo源码中实现的一个注册中心扩展.它很特殊,也帮我解决了一个困扰已久的问题,刚刚在生产中用了,效果很好,迫不及待想分享给大家. Dubbo的扩展性非常灵活,可以无侵入源码加载自定 ...

  6. Ubuntu service 命令

    启动指定服务 sudo service 服务名 start 停止指定服务 sudo service 服务名 stop 重启指定服务 sudo service 服务名 start 查看所有服务 sudo ...

  7. B快速导航

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

  8. 以鶸ice为例,手撸一个解释器(一)明确目标

    代码地址 # HelloWorld.ice print("hello, world") 前言(废话) 其实从开始学习编译原理到现在已经有快半年的时间了,但是其间常常不能坚持看下去龙 ...

  9. Solution -「NOI 模拟赛」彩色挂饰

    \(\mathcal{Description}\)   给定一个含 \(n\) 个点 \(m\) 条边的简单无向图,设图中最大点双的大小为 \(s\),则保证 \(s\le6\).你将要用 \(k\) ...

  10. JAVA8学习——Stream底层的实现四(学习过程)

    Stream的深入(四) 从更高角度去看一下:类与类之间的设计关系 (借助IDEA的图形处理工具 Ctrl+Alt+U). ReferencePipeline的三个实现的子类: Head Statel ...