leetcode-cn上面刷题
https://leetcode-cn.com/problemset/database/
---------------------------------------------------------------------------------
转载, 原文:https://www.cnblogs.com/By-ruoyu/p/11311830.html
最近开始重拾算法,在 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%
。
这个算法还是有可以改进的地方,但是若羽现在暂时还没有思路如何再进一步将查询复杂度降下去,这里可能需要自己实现一个更高效的哈希算法。
写在最后
许久没有接触算法了,有些生疏,思路上也有些堵塞。这里若羽对于接下来进一步优化有一些初步的想法,待有空实验后再加一篇解题报告。
分段策略,当数据量达到一定程度时使用更高效的算法,当数据量较小时,可能哈希耗时会更长一些,这个需要实验。大意便是寻找多个算法的耗时阈值,利用阈值进行策略选择。
自己实现针对题目更高效的哈希算法。
https://leetcode-cn.com/problemset/database/
leetcode-cn上面刷题的更多相关文章
- LeetCode面试常见100题( TOP 100 Liked Questions)
LeetCode面试常见100题( TOP 100 Liked Questions) 置顶 2018年07月16日 11:25:22 lanyu_01 阅读数 9704更多 分类专栏: 面试编程题真题 ...
- onhashchange事件,只需要修改hash值即可响应onhashchange事件中的函数(适用于上一题下一题和跳转页面等功能)
使用实例: 使用onhashchange事件做一个简单的上一页下一页功能,并且当刷新页面时停留在当前页 html: <!DOCTYPE html><html><body& ...
- LeetCode高频148错题记录
3. Max Points on a Line 共线点个数3种解法 思路一:思考如何确定一条直线,两点法,确定斜率后带入一点.有三种情况,1. 两点重合,2. 斜率不存在,3. 正常算,依次以每个点为 ...
- CodeForces813E:Army Creation (主席树---上一题的加强版)
As you might remember from our previous rounds, Vova really likes computer games. Now he is playing ...
- LeetCode上并发题目无Go版本:台湾同胞试水 — 交替打印FooBar
https://mp.weixin.qq.com/s/I5va3PI1oGIj8R_n3Nw2yw
- [LeetCode] 接雨水,题 Trapping Rain Water
这题放上来是因为自己第一回见到这种题,觉得它好玩儿 =) Trapping Rain Water Given n non-negative integers representing an eleva ...
- 每日温度(LeetCode Medium难度算法题)题解
LeetCode 题号739中等难度 每日温度 题目描述: 根据每日 气温 列表,请重新生成一个列表,对应位置的输入是你需要再等待多久温度才会升高超过该日的天数.如果之后都不会升高,请在该位置用 0 ...
- 我在LeetCode的首次刷题
到现在为止,我才发现我的博客一篇感受,心得,体会之言都没有. 今天就来随便扯扯. 刷题,是我最近一直在干的事情.也就每天写一两个.忘了就没写这种.也收藏了好几个刷题网站,当然第一次接触肯定是 WUST ...
- 2019招商银行M-Geeker线上比赛题解析
目录 1. 最大子序和(变体) 2. 矩阵求乘积最大 3. 逐渐平均--值最大 目前已更新:第一题,第二题,第四题 1. 最大子序和(变体) 题目描述: 首先考虑常规的最大子序和的问题,即不能去掉中间 ...
随机推荐
- ggplot绘图之基本语法
ggplot绘图之基本语法 2018年09月03日 22:29:56 一个人旅行*-* 阅读数 4332更多 分类专栏: R语言 1.ggplot2图形之基本语法: ggplot2的核心理念是将绘 ...
- 解决jQuery版本冲突
解决jquery版本冲突问题 <!-- 引入1.6.4版的jq --><script src="http://ajax.googleapis.com/ajax/libs/j ...
- 最新 安易迅java校招面经 (含整理过的面试题大全)
从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿. 安易迅等10家互联网公司的校招Offer,因为某些自身原因最终选择了 安易迅.6.7月主要是做系统复习.项目复盘.Leet ...
- P1308(字符串类,处理字符串查找)
题目描述 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数. 现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给 ...
- 100天搞定机器学习|day54 聚类系列:层次聚类原理及案例
几张GIF理解K-均值聚类原理 k均值聚类数学推导与python实现 前文说了k均值聚类,他是基于中心的聚类方法,通过迭代将样本分到k个类中,使每个样本与其所属类的中心或均值最近. 今天我们看一下无监 ...
- 07 UML类图
移步: https://www.cnblogs.com/coolstream/p/9572846.html
- access函数的使用
#include<unistd.h> int access(const char* pathname, int mode); 参数介绍: pathname 是文件的路径名+文件名 mode ...
- idea的项目结构
idea项目结构: 一般是创建一个empty project,然后再创建一个个的Module.
- shiro是什么?
是什么? Shiro是一个非常强大的.易于使用的.开源的.权限框架.它包括了权限校验.权限授予.会话管理.安全加密等组件. 为什么要使用shiro? 如果你是需要设计RBAC(Role Based A ...
- 使用dockers安装MySQL
事前准备 关闭selinux setenforce 0 vim /etc/sysconfig/selinux SELINUX=disabled # 若不关闭,使用docker启动mysql5.7镜像容 ...