Leetcode1——两数之和

题目分类:数组、哈希表的应用

1. 题目描述

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

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。(原题网址:https://leetcode-cn.com/problems/two-sum/)

示例1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例2:

输入:nums = [3,2,4], target = 6
输出:[1,2]

示例3

输入:nums = [3,3], target = 6
输出:[0,1]

2. 解法

2.1 暴力匹配

这个应该是最容易想到的解法了,既然答案说了一定只有一个组合成立,我们只要使用两个for循环,遍历一下nums数组,如果nums[i] + nums[j] == target,那么就输出对应的i和j即可。

class Solution {
public int[] twoSum(int[] nums, int target) {
for (int i = 0; i < nums.length; i++) {
for (int j = i+1; j < nums.length; j++) {
if (nums[i] + nums[j] == target) {
return new int[] {i, j};
}
}
}
return new int[0];
}
}

注意:有返回值的Java方法要求最后一定有确定的返回值,即你的return语句不能全部都在条件分支里面(万一分支条件均不满足,那么就出错了),所以在最后一行也会放上一个return语句,像本题我们放上一个长度为0的数组(代表没有找到结果),但是题中描述说必有一个唯一解,实际上这个语句永远不会运行,若是不加则会报错哦。

复杂度分析

假设问题的规模为n(这里即是数组长度为n)

我们使用了两个for循环,最坏的情况是比较全部元素后才发现目标元素,即比较次数为\(\frac{n(n-2)}{2}\),那么时间复杂度为\(O(n^2)\)。额外存储空间为常数,故空间复杂度为\(O(1)\)。

能不能将时间复杂度降低一些呢?首先来分析一下暴力破解法,其相当于选定nums[i]再从i到n-1中选取target - nums[i],而这个寻找target - nums[i]的操作时间复杂度是\(O(n)\),这是因为我们无法直接确定target - nums[i]的位置,需要逐个比较确定。

2.2 哈希表解法

暴力破解法的困难可以用HashMap来解决,我们可以将nums[i]——i以键值对的形式存储在哈希表中,这样就可以以O(1)的时间复杂度找到target - nums[i]。

2.2.1 一个笨笨的代码

class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> hash = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
hash.put(nums[i], i);
}
for (int i = 0; i < nums.length; i++) {
while (hash.containsKey(target - nums[i]) &&
(hash.get(target - nums[i]) != i)) {
return new int[] {hash.get(target - nums[i]), i};
}
}
return new int[0];
}
}

代码分析

首先将全部键值对存到哈希表中,这个操作时间复杂度为O(n)。接下来使用一个for循环来遍历nums,注意,这里内层仍选用了一个while循环!这个while循环是为了避免在哈希表查找到i(也就是当前遍历到的)的值,这样就相当于使用了一个元素多次。所以,当查找到的数组下标为仍为i时,需要重新查找一下,找到除了当前元素的其它target - nums[i]。这个while最多只会运行2次,所以不会是时间复杂度为\(O(n^2)\),该步骤时间复杂度仍为O(n)。故整体的时间复杂度仍为O(n)。时间复杂度大大降低啦!但是代价是空间复杂度飙升到O(n)。

2.2.2 更聪明的代码

在使用哈希表时,我们先将nums[i]和i全部存到哈希表中再进行查找,能不能把代码进一步优化一下呢?而且上一组代码的while使用有些丑陋,下面给出更优雅的实现(leetcode官方题解

class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> hashtable = new HashMap<Integer, Integer>();
for (int i = 0; i < nums.length; ++i) {
if (hashtable.containsKey(target - nums[i])) {
return new int[]{hashtable.get(target - nums[i]), i};
}
hashtable.put(nums[i], i);
}
return new int[0];
}
}

官方的解法通过在寻找target - nums[i]后构造哈希表的方式,有效避免了哈希表查到自己的麻烦(笨笨的解法),而且缩短了代码行数。

如何避免麻烦的解释:在查找target - nums[i]时,nums[i]的键值对未存到哈希表中,也就是此时只能查到数组下标不是i但值为target - nums[i]的元素。而且只用了一个for循环就解决了问题,十分简洁。

3. 总结

本题虽然很简单,但还是有着许多解法的,本题除了以上两种解法还可以先将数组排序(不妨设选用的是平均时间复杂度为O(nlogn)的排序,例如快速排序、归并排序),在遍历有序数组的时候利用二分查找快速查找target - nums[i],整体平均时间复杂度为O(nlogn),这同样也是一种很好的思路。在学习算法的时候也是一样,在解出题目后要分析其时间和空间复杂度,看看能否优化。

Leetcode1——两数之和 详细解析的更多相关文章

  1. LeetCode1——两数之和

    最近在家拧三阶魔方,把初级的玩法掌握了,也就是可以还原六个面了,速度不快,但是也很兴奋.三阶魔方的初级玩法按照套路拧就可以了,每一步需要完成的任务,该步骤转动的方法基本都是固定的,而且变化也并不是特别 ...

  2. Leetcode-1.两数之和

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

  3. [Swift]LeetCode1 .两数之和 | Two Sum

    Given an array of integers, return indices of the two numbers such that they add up to a specific ta ...

  4. LeetCode1.两数之和 JavaScript

    给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用. 实例: 给定 nums = [2, 7, 11, 15], target ...

  5. Leetcode1.两数之和——简洁易懂

    > 简洁易懂讲清原理,讲不清你来打我~ 输入一个数组和一个整数,从数组中找到两个元素和为这个整数,输出下标![在这里插入图片描述](https://img-blog.csdnimg.cn/img ...

  6. 前端与算法 leetcode 1. 两数之和

    目录 # 前端与算法 leetcode 1. 两数之和 题目描述 概要 提示 解析 解法一:暴力法 解法二:HashMap法 算法 传入[1, 2], [11, 1, 2, 3, 2]的运行结果 执行 ...

  7. LeetCode_#1_两数之和 Two Sum_C++题解

    1. 两数之和 Two Sum 题目描述 Given an array of integers, return indices of the two numbers such that they ad ...

  8. 【LeetCode】 两数之和 twoSum

    两数之和 (简单) 题目描述 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数: 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用. 例如: 给定 nums = [2,7,11, ...

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

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

随机推荐

  1. 【.net】AppDoamin| 应用程序域

    在.net framework框架上,一个进程可以有多个appdomain.因此一个进程可以运行多个程序. 应用程序域的出现: (来自msdn)    在.net出现以前,一个进程下,只能运行一个应用 ...

  2. bool? int?等可为空的数值类型的运算 三值逻辑

    算术运算:(+,-,*,/)时,只要一个为null,则结果为null. 比较运算符: <.>.<= 和 >=,也是如此.如果一个或全部两个操作数都为 null,则结果为 fal ...

  3. 2019CCPC Final K. Russian Dolls on the Christmas Tree

    题目大意 一棵 \(n(1\leq n\leq 2\times 10^5)\) 个节点以 \(1\) 为根的树,分别求以 \(1\sim n\) 为根的子树中有多少个节点编号连续的段. \(T(1\l ...

  4. dopamine源码解析之dqn_agent

    目录 epsilon函数 DQNAgent构造函数核心参数 DQNAgent核心函数 tf.make_template 核心数据流图 epsilon函数 linearly_decaying_epsil ...

  5. 高颜值测试报告- XTestRunner

    Modern style test report based on unittest framework. 基于unittest框架现代风格测试报告. 特点 漂亮测试报告让你更愿意编写测试. 支持单元 ...

  6. javascript、css3曲线运动示例记录

    想做一个加入购物车的曲线动效,网上找到两个demo,分别是js和css3实现的. js:https://www.cnblogs.com/wangmeijian/p/5824176.html jquer ...

  7. CentOS7部署Bind

    镜像下载.域名解析.时间同步请点击 阿里巴巴开源镜像站 1.简介 DNS(Domain Name System),域名系统,因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问 ...

  8. IDEA版部署离线ArcGIS api for JavaScript

    痛苦!折磨! 这两天发现IDEA 做ArcGIS api 开发比EClipse好用(重点是没有JS提示).但引入的ArcGIS api 一直报错,说找不到.这两天思来想去就是不知道为什么找不到loca ...

  9. [XMAN筛选赛](web)ctf用户登录

    0x00 题目概述 就只写了几道web题,有些考察点比较明显,所以个人感觉来说web总体不难. 一航的writeup写得差不多,我这写个他没写的wirteup. 看题: 链接点进去是一个登录页面,习惯 ...

  10. Axure7.0 以及 中文汉化语言包下载 axure汉化包

    支持 Axure RP Pro 正式版 当前最新版本 7.0.0.3184 不兼容6.5及以下版本! Axure7.0 下载地址:http://pan.baidu.com/s/1dEuR8YX Axu ...