JavaScript的two-sum问题解法
一个很常见的问题,找出一个数组中和为给定值的两个数的下标。为了简单一般会注明解只有一个之类的。
最容易想到的方法是循环遍历,这里就不说了。
在JS中比较优雅的方式是利用JS的对象作为hash的方式:
var twoSum = function(nums, target) {
var hash = {};
var i;
for (var i = 0; i < nums.length; i++ ) {
if (typeof hash[nums[i]] !== "undefined") {
return [i, hash[nums[i]]];
}
hash[target - nums[i]] = i;
}
};
这里面还可以做一些小的优化,比如把length拿出来,重复使用的 nums[i] 也抽取出来,遍历的顺序反过来等,最后大概弄成这个样子:
var twoSum2 = function(nums, target) {
var hash = {};
var i;
var tmp;
for (i = nums.length; i--; ) {
tmp = nums[i];
if (typeof hash[tmp] !== "undefined") {
return [i, hash[tmp]];
}
hash[target - tmp] = i;
}
};
不过这些小的优化基本上不影响大局,在leetcode上测试了好几遍,排名总在75%到85%之间浮动。居然连90%都没达到,我对你很失望
让我再想想……
哦对了我记得前几天看到过一个优化循环的方法叫做Duff Device来着,不如试试?
链接在这里 https://en.wikipedia.org/wiki/Duff%27s_device。(怎么插入链接来着?)
这东西我的大概理解就是就是把for循环稍微展开一下,本来循环80次的行为,改写成执行10次循环,每次循环里执行8次。这样可以省下一点调用for循环的开销。不过这个前提是for循环里的执行代码比较简单。如果耗时主要在每个循环里的话,这招就不太管用了听说。
于是我照着介绍的例子,把上面的代码改写了一下:
var twoSum1 = function(nums, target) {
var hash = {};
var i = 0;
var startIndex = nums.length % 8;
var iterations = nums.length / 8;
do { switch(startIndex) {
case 0: if(typeof hash[nums[i]] !== "undefined") {return [i, hash[nums[i]]]} hash[target - nums[i]] = i; i++;
case 7: if(typeof hash[nums[i]] !== "undefined") {return [i, hash[nums[i]]]} hash[target - nums[i]] = i; i++;
case 6: if(typeof hash[nums[i]] !== "undefined") {return [i, hash[nums[i]]]} hash[target - nums[i]] = i; i++;
case 5: if(typeof hash[nums[i]] !== "undefined") {return [i, hash[nums[i]]]} hash[target - nums[i]] = i; i++;
case 4: if(typeof hash[nums[i]] !== "undefined") {return [i, hash[nums[i]]]} hash[target - nums[i]] = i; i++;
case 3: if(typeof hash[nums[i]] !== "undefined") {return [i, hash[nums[i]]]} hash[target - nums[i]] = i; i++;
case 2: if(typeof hash[nums[i]] !== "undefined") {return [i, hash[nums[i]]]} hash[target - nums[i]] = i; i++;
case 1: if(typeof hash[nums[i]] !== "undefined") {return [i, hash[nums[i]]]} hash[target - nums[i]] = i; i++;
} } while (--iterations); };
嗯,看上去很厉害的样子。接下来在浏览器里测试一下:
先构造一个长度为1000的数组,来来来:
呃……好像没什么差别。把数据加大一点,到100000吧:
卧槽牛逼啊!赶紧把这个放leetCode上试试!
……
……
……
然而在leetCode上试了之后,虽然通过了,发现和之前的执行效率并没有多大差别……依然没有到90%
一定是leetCode上的单测数据太小了!于是自个儿在leetCode上的那个小输入框里粘贴了一个十几万长度的数据,跑了一遍,发现仍然没有什么卵用。
所以大概是我的测试方法有问题?数据翻了100倍时间居然并没有增加多少,好奇怪。
好吧,这个方法就暂时搁着。再想想其它歪主意。
用js自带的forEach做循环试试吧,说不定会比手写的要快点。于是有了下列代码:
var twoSum = function (nums, target) {
var hash = {};
var result = [];
nums.forEach(function (v, i) {
if (typeof hash[v] !== "undefined") {
result[0] = i;
result[1] = hash[v];
}
hash[target - v] = i;
});
return result;
}
不过这有个问题是,forEach循环没法正常地退出,所以无论怎样都要遍历一下整个数组,不能像前面那样找到正确的就退出了,感觉太好。
所以只能让它不正常地退出了:
var twoSum = function (nums, target) {
var hash = {};
var result = [];
try {
nums.forEach(function (v, i) {
if (typeof hash[v] !== "undefined") {
result[0] = i;
result[1] = hash[v];
throw "err";
}
hash[target - v] = i;
});
} catch (err) {
return result;
}
}
好的就这样,跑一下试试:
噢好吧,好歹过了90%……
想到更快的方法再更………………
JavaScript的two-sum问题解法的更多相关文章
- JavaScript中大数相加的解法
一.两个大正整数字符串相加 在JavaScript中,数值类型满足不了大数据容量计算,可以用字符串进行操作 function add(strNum1, strNum2) { // 将传进来的数字/数字 ...
- Max double slice sum 的解法
1. 上题目: Task description A non-empty zero-indexed array A consisting of N integers is given. A tripl ...
- [LintCode] Continuous Subarray Sum II
Given an integer array, find a continuous rotate subarray where the sum of numbers is the biggest. Y ...
- 5、JavaScript进阶篇②——函数、事件、内置对象
一.函数 1. 什么是函数 函数的作用,可以写一次代码,然后反复地重用这个代码. 如:我们要完成多组数和的功能. var sum; sum = 3+2; alert(sum); sum=7+8 ; a ...
- 4、JavaScript进阶篇①——基础语法
一.认识JS 你知道吗,Web前端开发师需要掌握什么技术?也许你已经了解HTML标记(也称为结构),知道了CSS样式(也称为表示),会使用HTML+CSS创建一个漂亮的页面,但这还不够,它只是静态页面 ...
- JavaScript学习笔记 - 进阶篇(1)- JS基础语法
前言 JavaScript能做什么? 1.增强页面动态效果(如:下拉菜单.图片轮播.信息滚动等) 2.实现页面与用户之间的实时.动态交互(如:用户注册.登陆验证等) JS进阶篇学习什么? 在JavaS ...
- Javascript进阶篇——(函数)笔记整理
这节是根据慕课网和JavaScript DOM编程艺术一书加起来做的笔记 什么是函数如果需要多次使用同一段代码,可以把它们封装成一个函数.函数(function)就是一组允许在你的代码里随时调用的语句 ...
- Javascript进阶篇——(流程控制语句)笔记整理
做判断(if语句)if语句是基于条件成立才执行相应代码时使用的语句.语法: if(条件){ 条件成立时执行代码 } 例子:假设你应聘web前端技术开发岗位,如果你会HTML技术,你面试成功,欢迎加入公 ...
- JavaScript进阶(四)
现在说说什么是函数.函数的作用可以写一次代码,然后反复的重用这个代码.如:我们要完成多组数和的功能.var sum;sum=3+2;alert(sum); sum=7+8;alert(sum);... ...
- JavaScript进阶--慕课网学习笔记
JAVASCRIPT—进阶篇 给变量取个名字(变量命名) 变量名字可以任意取,只不过取名字要遵循一些规则: 1.必须以字母.下划线或美元符号开头,后面可以跟字 ...
随机推荐
- Js ==和===的区别
===判断: Undefined === Undefined,返回 true Null === Null,返回 true null == undefined,返回 false NaN === NaN, ...
- css或者js文件后面跟着参数
以前一直不懂,看到某某网站上面css链接 ?v=20130203类似这样的 后来发现是为了避免浏览器读取缓存而采取的强制刷新缓存的办法. “比如新浪首页在2010年4月5日改版,只是改变CSS样式表, ...
- Django admin美化插件suit应用[原创]
前言 由于比较懒,自己弄了一个用户验证,没有自己写后台,用了django自带的user认证,并通过admin直接进行管理,但默认的admin并不漂亮,于是使用了这个django-suit插件,效果对比 ...
- APNS 远程推送通知 PUSH deviceToken
服务器向客户端推送消息: 当应用程序推到后台,或者根本就没有运行(我们的代码无能为力) 如果这种情况之下,应用程序想和用户交互(传统的做法 不可能) 推送 APNS:Ap ...
- NSwagStudio for Swagger Api
本案例主要说明如何使用NSwag 工具使用桌面工具快速生成c# 客户端代码.快速的访问Web Api. NSwagStudio 下载地址 比较强大.可以生成TypeScript.WebApi Cont ...
- Delphi_07_Delphi_Object_Pascal_基本语法_05_函数参数
这里主要讨论Delphi中函数.方法的相关内容. 一.工程文件 { Delphi语法方法和函数 1.方法 2.函数 } program Routine; {$APPTYPE CONSOLE} uses ...
- CSS3新特性应用之字体排印
一.插入换行 ~:表示同辈元素之后指定类型的元素,如;elm1 ~ elm2表示,elm1之后的所有elm2元素,且elm1与elm2都是在同一个父级元素. +:表示同辈元素的兄弟元素. \A:一个空 ...
- 仿QQ空间根据位置弹出PopupWindow显示更多操作效果
我们打开QQ空间的时候有个箭头按钮点击之后弹出PopupWindow会根据位置的变化显示在箭头的上方还是下方,比普通的PopupWindow弹在屏幕中间显示好看的多. 先看QQ空间效果图: ...
- 嵌入式:J-link刷固件(坑)
1.上电,短接ERASE,>10秒后,拔USB. 2.短接TST,上电,>10秒后,拔USB. 3.安装驱动.(看别人教程,下载到INF文件,WIN7不能右击安装,好,换虚拟机XP) 4. ...
- Google C++单元测试框架GoogleTest---Google Mock简介--概念及基础语法
就在昨天终于做了gtest的分享,我的预研工作终于结束了,感觉离我辞职的日子不远了,毕竟是专注java二百年啊,要告别实习啦.. 这篇是GoogleMock的简介文档,会在后边附带一个自己的例子. 一 ...