LeetCode :1.两数之和 解题报告及算法优化思路
最近开始重拾算法,在 LeetCode上刷题。顺便也记录下解题报告以及优化思路。
题目链接:1.两数之和
题意
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
nums = [2, 7, 11, 15], target = 9
返回 [0, 1]
题意很简单,就是寻找两个数,这两个数相加的值等于 target。且保证每组输入一定会有答案。
解题思路
从题意上看, 只需要找到那两个数即可。那么首先可以想到的就是枚举组合两个数的和,但是 组合数 的数量是非常大的,这个思路就可以作罢。
两个数相加的和等于 target, 反过来,对于一个数 nums[i],能否在数组里找到另外一个数 nums[j] 使得 nums[j] = target - nums[i]。这样我们只需要关心一个数即可。
暴力枚举
简单粗暴,一重循环用来枚举 nums[i], 另一重用来寻找 nums[j]。
代码:
public class Solution {
public int[] TwoSum(int[] nums, int target) {
for(int i = 0; i < nums.Length; i ++) {
int res = target - nums[i];
for(int j = 0; j < nums.Length; j ++) {
if(i == j) continue;
if(res == nums[j]) return new int[] {i, j};
}
}
return new int[] {};
}
}
执行用时:904ms
内存消耗:29.6MB
用时排名:超过21.29%
29个案例,耗时近 1 秒。 由于这里仅有循环辅助变量,内存消耗其实不大。
耗时排名是排在比较后面的,这也说明了还有更优的解法。
空间换时间
此题关键的地方在于:如何快速的找到 j,暴力枚举在最坏的情况下会找遍整个数组,直到最后一个才找到,时间复杂度也就是 O(n)。
那么,在这里我们可以利用 哈希算法 进行映射,从而达到更快查找效率。理论上 哈希算法 设计良好的情况下可以达到 常数级 O(1) 的复杂度。
一个例子:在值不大的情况下, 可以用值当做数组下标,而数组的值作为原来数组的下标。即:
对于 x = nums[i],存在 hash[x] = i。这样在牺牲大量空间的情况下可以使得查询效率达到极致的常数级 O(1)。
但是很遗憾, 这道题并没有办法直接使用这个方法,因为 int.MaxValue 是远超过了数组可以定义的范围。编译时会报错,内存溢出。
既然暂时没有办法达到 O(1) 的地步, 那么可以考虑使用实现了 哈希算法 (这里保留说法,若羽源码没有阅读完,在看到index的取法有着很明显的哈希痕迹进行猜测的)的 Dictionary<TKey, TValue>。
代码:
public class Solution
{
public int[] TwoSum(int[] nums, int target)
{
var dic = new Dictionary<int, List<int>>();
for(int i = 0; i < nums.Length; i ++)
{
int num = nums[i];
int res = target - num;
if(dic.ContainsKey(res))
{
return new int[] {i, dic[res][0]};
}
if(!dic.ContainsKey(num))
{
dic.Add(num, new List<int>(){});
}
dic[num].Add(i);
}
return new int[] {};
}
}
执行用时:468 ms
内存消耗:30.5MB
用时排名:超过78.61%
改进后的算法排名与之前可谓是天差地别,已经到了前 30%。
仅仅是达到了前三分之一,说明这个算法还有可以更进一步的优化。
进一步优化查询
这里用了 Dictionary, 但这里的 TValue 是一个列表。仔细想想,这里我们是不需要保存列表的,只需要保存一个值即可,因为只需要找到一组答案即可!
其次可以减去第二个判断,并不需要判断是否存在,直接覆盖/新建即可。
最后可以反向查询,查之前的数值中是否缺一个 nums[i],对应存进去的就是差值,这样可以减去两个临时变量,顺带优化一点点的空间。
代码:
public class Solution
{
Dictionary<int, int> dic = new Dictionary<int, int>();
public int[] TwoSum(int[] nums, int target)
{
if(nums.Length == 2) return new int[] {0, 1};
dic.Clear();
for (int i = 0; i < nums.Length; i++)
{
if(dic.ContainsKey(nums[i])) return new int[] {dic[nums[i]], i};
dic[target - nums[i]] = i;
}
return new int[] { };
}
}
执行用时:360 ms
内存消耗:30MB
用时排名:超过98.83%
改进后的算法相比之前的差距并不是非常的大,但就是这百来毫秒的差距,排名上升到了前 3%。
这个算法还是有可以改进的地方,但是若羽现在暂时还没有思路如何再进一步将查询复杂度降下去,这里可能需要自己实现一个更高效的哈希算法。
写在最后
许久没有接触算法了,有些生疏,思路上也有些堵塞。这里若羽对于接下来进一步优化有一些初步的想法,待有空实验后再加一篇解题报告。
分段策略,当数据量达到一定程度时使用更高效的算法,当数据量较小时,可能哈希耗时会更长一些,这个需要实验。大意便是寻找多个算法的耗时阈值,利用阈值进行策略选择。
自己实现针对题目更高效的哈希算法。
LeetCode :1.两数之和 解题报告及算法优化思路的更多相关文章
- LeetCode :2.两数相加 解题报告及算法优化思路
题目连接:2.两数相加 题意 题目难度标为 中等, 因为题意上有一部分理解难度,以及需要数据结构的链表基础. 还不知道到链表的童鞋可以粗略的看下百度百科或者是翻出数据结构的书看一看,通俗一点的语言来解 ...
- 前端与算法 leetcode 1. 两数之和
目录 # 前端与算法 leetcode 1. 两数之和 题目描述 概要 提示 解析 解法一:暴力法 解法二:HashMap法 算法 传入[1, 2], [11, 1, 2, 3, 2]的运行结果 执行 ...
- LeetCode:两数之和、三数之和、四数之和
LeetCode:两数之和.三数之和.四数之和 多数之和问题,利用哈希集合减少时间复杂度以及多指针收缩窗口的巧妙解法 No.1 两数之和 给定一个整数数组 nums 和一个目标值 target,请你在 ...
- Leetcode 001. 两数之和(扩展)
1.题目要求 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用. 示例: 2.解法一:暴力法(for*for,O(n*n)) ...
- LeetCode 653. 两数之和 IV - 输入 BST(Two Sum IV - Input is a BST)
653. 两数之和 IV - 输入 BST 653. Two Sum IV - Input is a BST 题目描述 给定一个二叉搜索树和一个目标结果,如果 BST 中存在两个元素且它们的和等于给定 ...
- leetCode:twoSum 两数之和 【JAVA实现】
LeetCode 两数之和 给定一个整数数组,返回两个数字的索引,使它们相加到特定目标. 您可以假设每个输入只有一个解决方案,并且您可能不会两次使用相同的元素. 更多文章查看个人博客 个人博客地址:t ...
- Leetcode 1. 两数之和 (Python版)
有粉丝说我一个学算法的不去做Leetcode是不是浪费,于是今天闲来没事想尝试一下Leetcode,结果果断翻车,第一题没看懂,一直当我看到所有答案的开头都一样的时候,我意识到了我是个铁憨憨,人家是让 ...
- 每天一道面试题LeetCode 01 -- 两数之和
Two Sum 两数之和 Given an array of integers, find two numbers such that they add up to a specific target ...
- Leetcode 167. 两数之和 II - 输入有序数组 By Python
给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数. 函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2. 说明: 返回的下标值 ...
随机推荐
- (持续更新)Qt3D 学习资源
目录 一.前言 1.1 什么是Qt3D 1.2 Qt3D 的利与弊 利:原生支持 弊处:资料过少 二.学习建议 2.1 OpenGL 学习资料 2.2 Qt3D 资料 2.2.1 视频资料 2.2.4 ...
- scrapy基础知识之 使用FormRequest.from_response()方法模拟用户登录:
通常网站通过 实现对某些表单字段(如数据或是登录界面中的认证令牌等)的预填充 使用Scrapy抓取网页时,如果想要预填充或重写像用户名.用户密码这些表单字段, 可以使用 FormRequest.fro ...
- c++ 广度优先搜索(宽搜)
c++ bfs基本应用 Knight Moves 题目描述 贝茜和她的表妹在玩一个简化版的国际象棋.棋盘如图所示: 贝茜和表妹各有一颗棋子.棋子每次移一步,且棋子只能往如图所示的八个方向移动.比赛的规 ...
- 转: windows系统下mysql出现Error 1045(28000) Access Denied for user 'root'@'localhost'
windows系统下mysql出现Error 1045(28000) Access Denied for user 'root'@'localhost' 转自 http://zxy5241.space ...
- Apache Dubbo已不再局限于Java语言
2017 年 9 月 7 日,在沉寂了4年之后,Dubbo 悄悄的在 GitHub 发布了 2.5.4 版本.随后又迅速发布了 2.5.5.2.5.6.2.5.7 等release.在 2017年 1 ...
- [NOIP2013]华容道 题解(搜索)
[NOIP2013]华容道 [题目描述] 这道题根据小时候玩华容道不靠谱的经验还以为是并查集,果断扑街.考后想想也是,数据这么小一定有他的道理. 首先由于是最小步数,所以BFS没跑了.那么我们大可把这 ...
- ~~函数基础(二):返回值&作用域~~
进击のpython 函数的返回值和作用域 上文我们讲到了函数的基础--参数的相关问题 举的例子也都是带有print的函数定义 但是有个问题就出现了:我不想打印这个函数处理后的参数 我想拿到这个参数然后 ...
- Spring Cloud学习(一):Eureka服务注册与发现
1.Eureka是什么 Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的. Eureka ...
- py+selenium+IE10【IE已停止工作】【已解决】
问题:跑自动化时,到某个用例IE就崩,提示已停止工作. 手工跑的时候,IE挂,提示“Internet Explorer 已经为了帮助保护您的计算机而关闭此网页”. 且每次都在需要调用flash插件 ...
- TF项目实战(SSD目标检测)-VOC2007
TF项目实战(SSD目标检测)-VOC2007 训练好的模型和代码会公布在网上: 步骤: 1.代码地址:https://github.com/balancap/SSD-Tensorflow 2.解压s ...