No.001:Two Sum
问题:
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
官方难度:
Easy
翻译:
给定一个整型数组和一个给定值,返回数组中两数的下标,这两数的和为给定值,假设解集唯一确定。
例子:
给定数组{2,7,11,15},给定值9,返回下标[0,1]。
方法一:
- 利用一个二次循环,在之后的数组中查找target-nums[i]是否存在。
方法一的解题代码:
public static int[] method_1(int[] nums, int target) {
for (int i = 0; i < nums.length - 1; i++) {
int numberToFind = target - nums[i];
for (int j = i + 1; j < nums.length; j++) {
if (nums[j] == numberToFind) {
return new int[] { i, j };
}
}
}
throw new IllegalArgumentException("No two sum solution");
}
method_1
方法二:
- 相对而言,在Java里面,数组是一种帮助方法相对较少的数据结构,我们可以期盼,有一种方法,可以快速的定位是否存在某一个给定的值,那么相对就可以减少内循环的时间开销。
- 第一个想法是List集合,List集合有List.contains()方法,迅速定位List集合中是否存在某一给定的元素,同时数组的帮助方法Arrays.asList(),可以直接将数组转化为List集合。同时,还有List.indexOf()方法,来定位下标。
- 想法总是美好的,但是这一方法的雷区实在太多。
- 数组和集合有一个很重要的差别在于,集合不能接收基本类型,你可能会想象Arrays.asList()能触发自动装箱,但是很可惜,int[]也是List集合能够接收的类型。所以你需要先显式地将int[]转化为Integer[]。
- List.indexOf(target)是获取集合中第一个为target的下标,那么就无法定位例如nums[]={2,1,2},target=4的问题。这时候自然地会想到利用List.lastIndexOf()方法。但是问题又来了,例如nums[]={3,2,4},target=6的问题,返回的数组为[0,0],所以要优先加上index1!=idnex2的判断条件。
- 鉴于有这么多的雷区,就时间消耗上看,也不见得有多少提升,可能还比方法一有所不如,不推荐使用这种方法。
方法二的解题代码:
public static int[] method_2(int[] nums, int target) {
// 先将int[]转成Integer[]
Integer[] collectionArray = new Integer[nums.length];
for (int i = 0; i < nums.length; i++) {
collectionArray[i] = nums[i];
}
List<Integer> list = new ArrayList<>();
list = Arrays.asList(collectionArray);
for (Integer a : list) {
if (list.contains(target - a)) {
// 防止原数组有重复数字的情况
int index1 = list.indexOf(a);
int index2 = list.lastIndexOf(target - a);
if (index1 != index2) {
return new int[] { index1, index2 };
}
}
}
throw new IllegalArgumentException("No two sum solution");
}
method_2
方法三:
- 无论是方法一,还是方法二的算法,最大的缺点在于,它需要在剩余数组中寻找结果,当数组很大的时候,这种时间开销就相当庞大了。其实我们可以将已经遍历过的数字放入另一个数据结构中,在这个数据结构中寻找解集。
方法三的解题代码:
public static int[] method_3(int[] nums, int target) {
List<Integer> list = new ArrayList<>();
list.add(nums[0]);
for (int i = 1; i < nums.length; i++) {
if (list.contains(target - nums[i])) {
return new int[] { list.indexOf(target - nums[i]), i };
}
list.add(nums[i]);
}
throw new IllegalArgumentException("No two sum solution");
}
method_3
方法四:
- 仔细分析方法三中算法的时间开销,不难发现List.contains()方法在List集合中查找的效率决定了整个算法的时间开销。那么List.contains()是不是最优的查找方式呢?
- 说到查找速度,不可避免地想到了哈希表,自然而然的,就考虑尝试使用HashMap的数据结构,将nums[i]作为key,i作为value,同时Map集合提供Map.containsKey()方法在HashMap的实现上,拥有更高的效率。
方法四的解题代码:
public static int[] twoSum(int[] nums, int target) {
if (nums == null || nums.length < 2) {
throw new IllegalArgumentException("Input error");
}
Map<Integer, Integer> map = new HashMap<>();
map.put(nums[0], 0);
for (int i = 1; i < nums.length; i++) {
int numberToFind = target - nums[i];
if (map.containsKey(numberToFind)) {
return new int[] { map.get(numberToFind), i };
}
map.put(nums[i], i);
}
throw new IllegalArgumentException("No two sum solution");
}
twoSum
备注:
- 一般的算法,需要考虑入参的合理性,这一点在方法四的代码中有写出。
- 可以将第一个元素直接放入集合,循环从i=1开始,可以省去一次判断的操作。
- 虽然哈希表拥有很高的速度,但是Map的空间的开销要远比List来得多,如果效率提升不大的话,尽可能还是不要用Map了。当然,本题中对于时间效率的提升还是值得的。
相关链接:
https://leetcode.com/problems/two-sum/
PS:如有不正确或提高效率的方法,欢迎留言,谢谢!
No.001:Two Sum的更多相关文章
- 通过位运算求两个数的和(求解leetcode:371. Sum of Two Integers)
昨天在leetcode做题的时候做到了371,原题是这样的: 371. Sum of Two Integers Calculate the sum of two integers a and b, b ...
- LeetCode 题解(一):Two Sum
LeetCode : two sum 第一次写博客,算是熟悉这些编辑环境吧,本来是打算在csdn上用markdown写的,结果改了博客介绍就被关闭了,晕死...好了,话不多说,今天打算拿LeetCod ...
- Python3练习题 001:4个数字求不重复的3位数
#Python练习题 001:4个数字求不重复的3位数#方法一import itertoolsres = [][res.append(i[0]*100 + i[1]*10 + i[2]) for i ...
- 实用ExtJS教程100例-001:开天辟地的Hello World
ExtJS功能繁多,要想彻底的了解确实很困难.作为初学者,如何能找到一条快速的通道呢?我觉得,如果你有Javascript的基础,那就不要惧怕ExtJS的复杂,从动手开始,遇到问题,解决问题,积累经验 ...
- LeetCode-1:Two Sum
[Problem:1-Two Sum] Given an array of integers, return indices of the two numbers such that they add ...
- HDU1244:Max Sum Plus Plus Plus
题目链接:Max Sum Plus Plus Plus 题意:在n个数中取m段数使得这m段数之和最大,段与段之间不能重叠 分析:见代码 //dp[i][j]表示前i个数取了j段的最大值 //状态转移: ...
- SQL-W3School-函数:SQL SUM() 函数
ylbtech-SQL-W3School-函数:SQL SUM() 函数 1.返回顶部 1. SUM() 函数 SUM 函数返回数值列的总数(总额). SQL SUM() 语法 SELECT SUM( ...
- 数据测试001:利用python连接数据库插入excel数据
数据测试001:利用python连接数据库插入excel数据 最近在做数据测试,主要是做报表系统,需要往数据库插入数据验证服务逻辑,本次介绍如何利用python脚本插入Oracle和Mysql库中: ...
- HDU 1024:Max Sum Plus Plus(DP)
http://acm.hdu.edu.cn/showproblem.php?pid=1024 Max Sum Plus Plus Problem Description Now I think you ...
随机推荐
- cmd实用命令
1.netstat 查看电脑端口状况 实际应用举例:查看某软件坚监听的电脑端口. 在任务管理器中选择列...,打开PID的显示.在这里查看某个应用程序的线程ID是多少.例如QQ:4904. 运行,cm ...
- 2015.10.14-TransactionScope测试
测试代码: ; ; List<string> lst = null; Action doSth = () => { using (var db = new TestSystemEnt ...
- 【Cocos2d-Js基础教学(2)类的使用和面向对象】
类的使用和面向对象 大家都知道在cocos2d-x 底层是C++编写的,那么就有类的概念和继承机制. 但是在JS中,是没有类这个概念的,没有提供类,没有C++的类继承机制. 那么JS是通过什么方式实现 ...
- html5网页动画总结--jQuery旋转插件jqueryrotate
CSS3 提供了多种变形效果,比如矩阵变形.位移.缩放.旋转和倾斜等等,让页面更加生动活泼有趣,不再一动不动.然后 IE10 以下版本的浏览器不支持 CSS3 变形,虽然 IE 有私有属性滤镜(fil ...
- 使用Doxygen生成net帮助文档
一. 什么是Doxygen? Doxygen 是一个程序的文件产生工具,可将程序中的特定批注转换成为说明文件.通常我们在写程序时,或多或少都会写上批注,但是对于其它人而言,要直接探索程序里的批注,与打 ...
- React Native Android增加本地图片
将图片文件 UePbdph.png 放入与index.android.js的同目录中,在index.android.js中引入: <Image source={require('./UePbdp ...
- 在ASP.NET开发中容易忽略的2个小问题
本文地址:http://www.cnblogs.com/outtamyhead/p/3642729.html,转载需保留本地址. 最近在我的MVC项目中出现了两个非常小,但是往往惹出大麻烦的问题,借中 ...
- Bower 手册
安装 Bower 使用 npm 安装 Bower.(Bower 依赖于 Node, npm 和 Git.) $ npm install -g bower 基本用法 安装程序包 程序包安装命令 bowe ...
- JavaScript TDD with Mocha
开发现状 当新的版本快要发布的时候,大家都忙于加班,加紧修复BUG1.BUG2.我想这就是很多公司开发的现状. 为了不至于让上线的版本挂掉挂掉,少不了就是 人肉测试. 在一个项目中,我们会做许许多多各 ...
- [Math] A love of late toward Mathematics - how to learn it?
Link: https://www.zhihu.com/question/19556658/answer/26950430 王小龙 ,数学,计算机视觉,图形图像处理 数学系博士怒答! 我想大家 ...