当前位置: 首页 > news >正文

算法题复盘+代码解读(2)—— 两数之和

题目:给定一个整数数组 nums 和一个整数目标值 target ,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。可以假设每种输入只会对应一个答案,并且不能使用两次相同的元素。


可能应用场景:

电商平台的优惠券和促销系统等。

购物车中的商品价格cart_prices = [ 199, 299, 399, 99, 599]

而优惠券是满500-100的,coupon_target = 500

那就可以寻找两件商品价格之和超过500的最优组合

indices = twoSumVariant( cart_prices , coupon_target) ,返回最优组合的索引,即对应的商品


文字思路:

第一个想到的办法肯定是暴力枚举,一个一个加起来,看看是否等于target值就可以了。

第二办法是哈希表,这个东西其实对初学者挺难理解的,核心思想是记下见过的值。

首先准备工作是创建一个笔记本(哈希表),用来记录数值和它的序号;

流程是边看边记,边记边找。假如数组是[2, 7,11, 15],目标值是9,我首先看到的是数值2,位置是0(边看边记),思考我要找的是 9 - 2 = 7,检查笔记本里面没有7,就把数值2和位置0记进笔记本里;接着往下看(循环),发现是7,思考我要找的是 9 - 7 = 2,检查笔记本里有2,那就对了,那我就返回对应的结果[ 0,1];如果一直没找到,就返回空表示无解。

强化理解:比如你需要50元,你自己有20元,那这个时候你并不需要每个人都去问“你有30元吗”,而是只知道每个人有多少钱,当遇到有30元的人时,就可以立刻合作,减少了询问的次数。


暴力枚举代码:

int* twoSum(int* nums, int numsSize, int target, int* returnSize) {for (int i = 0; i < numsSize; ++i) {for (int j = i + 1; j < numsSize; ++j) {if (nums[i] + nums[j] == target) {int* ret = malloc(sizeof(int) * 2);ret[0] = i, ret[1] = j;*returnSize = 2;return ret;}}}*returnSize = 0;return NULL;
}

哈希表方法代码:

解读一下:这里的hashTable是先定义的一个结构体,后面这个hashtable是定义的一个指针,指向这个hashTable结构体,一开始看的时候会觉得怎么hashTable又来个hashtable的,到底什么关系,看的头都晕了。。UT_hash_handle hh是一个宏,是必须要有的,用来调用自带的一些方法。其余的代码就比较容易理解了。

struct hashTable {int key;int val;UT_hash_handle hh;
};struct hashTable* hashtable;struct hashTable* find(int ikey) {struct hashTable* tmp;HASH_FIND_INT(hashtable, &ikey, tmp);return tmp;
}void insert(int ikey, int ival) {struct hashTable* it = find(ikey);if (it == NULL) {struct hashTable* tmp = malloc(sizeof(struct hashTable));tmp->key = ikey, tmp->val = ival;HASH_ADD_INT(hashtable, key, tmp);} else {it->val = ival;}
}int* twoSum(int* nums, int numsSize, int target, int* returnSize) {hashtable = NULL;for (int i = 0; i < numsSize; i++) {struct hashTable* it = find(target - nums[i]);if (it != NULL) {int* ret = malloc(sizeof(int) * 2);ret[0] = it->val, ret[1] = i;*returnSize = 2;return ret;}insert(nums[i], i);}*returnSize = 0;return NULL;
}

C++哈希表方法实现:

很明显,C++的代码简洁很多,简单说说和C有哪些不同,便于快速上手C++。

按顺序,先从class(类)说起,可以理解它是C里面结构体的升级版,C++的class可以包含函数(称为成员函数或方法),C的struct只能包含数据。另外C++的class默认成员是private,也就是外部不能访问的,而struct默认是public,类外部是可以直接访问的,所以C++相当于是兼容了C。

vector是C++的动态数组,类似C的malloc,但他可以自动管理内存,无需手动分配和释放。

看到下面的第3行代码,vector<int> 表示这个函数返回的是一个整形的动态数组,twoSum是函数名;这个函数接收两个参数:nums和target,vector<int>& nums的意思是直接操作nums的原数组,而不是先把它拷贝进来再操作。

接着是第4行代码,这个unordered_map<>是C++里面创建哈希表的声明,<int,int>这个是表示键(key)和值(value)都是int类型,hashtable是自定义的变量名。

看到下面第5行代码,典型for循环,直接用nums.size()就可以获取nums数组的大小,确实是比C简洁多了,另外C++里面是更倾向与++i的。

来到第6行代码,auto是自适应参数类型的写法,it是自定义的名字,auto it 也可以写成int it,就这个意思。hashtable.find(x)是在哈希表里面查找键x,然后返回一个值,这里用auto it接收。

第7行代码,hashtable.end()表示最后一个元素的下一个元素,也就是空白处,说明找到的话,就执行第8行代码,返回{ it-> second, i},这是一个动态数组的写法,相当于将找到的两个下标打包成一个动态数组(vector<int>)返回,it->second表示哈希表中it对应的【值】,而first表示【键】,相当于C里面的key和value;i表示当前数字的索引。

代码来到第9行,num[i] 是当前哈希表的键(key),i是当前数组的索引(值)。

比如nums=[2, 7, 11, 15],那nums[0]是等于2的,nums[1]=7;

如果执行hashtable[2]=0,即hashtable[nums[0]]=0,就相当于哈希表里会有{2:0},再执行一个hashtable[7]=1,即hashtable[nums[1]]=1,哈希表里就会有{2:0, 7:1}。

最后一行,return {}; 表示返回一个空容器。

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

欢迎批评指正!

---------------------------------------------    END    ---------------------------------------------

http://www.dtcms.com/a/344803.html

相关文章:

  • 【功能测试面试题】
  • 【数据结构】B+ 树——高度近似于菌丝网络——详细解说与其 C 代码实现
  • CVPR焦点 | 神经网络新范式:轻量化与精度并行,重塑视觉任务性能天花板
  • 解释一下,Linux,shell,Vmware,Ubuntu,以及Linux命令和shell命令的区别
  • 1337俚语的由来
  • Seaborn数据可视化实战:Seaborn时间序列可视化入门
  • Linux学习-网络编程2
  • .java->.class->java 虚拟机中运行
  • 51.Seata-TCC模式
  • 前端函数防抖
  • Nginx + Keepalived 实现高可用负载均衡集群
  • 前端桌面端解决方案技术选型:全面指南
  • 深入理解强化学习的target network
  • 3.5MM防水耳机插座
  • 为什么访问HTTPS站点时,会发生SSL证书错误
  • JAVA基础代码示例
  • SpringBoot -- 集成Spring Security (二)
  • LightGBM时序预测详解:从原理到 PSO 参数优化
  • 如何理解面向过程和面向对象,举例说明一下?
  • [docker/大数据]Spark快速入门
  • 【实时Linux实战系列】实时系统中的预测性维护策略
  • 能源行业合同管理难点有哪些?企业该如何应对?
  • FIFO核心原理与机制
  • QGIS 绿色版修正
  • 基于vtkImageViewer2的MPR(二):改进
  • JavaScript 操作 DOM
  • 图论——Floyd算法
  • 四十一、【高级特性篇】API 文档驱动:OpenAPI/Swagger 一键导入测试用例
  • 上市公司能源消耗数据库
  • 【python】os.makedirs和with open