关于javascript 数组的正态分布排序的一道面试题
最近几天顶着上海40°的凉爽天气找工作,心里是开心的不要不要的,每次面试都是要坐那里出半天汗才能回过神来,感觉到了这个世界对我深深的爱意,言归正传,面试过程中碰到了几次笔试,其中有这么一道题,由于实际工作中没遇到过,所以留意下来,题目是这样:
有一个数组为:var arr = [1,2,1,3,3,2,4,6,3],通过处理将其变为正态分布的形式: [1,2,3,3,6,4,3,2,1]。
关于正态分布可以查看此链接:http://baike.baidu.com/link?url=OWbFf2pyVh3s5stnYYRdaqcwjg5-Fo4WRp1hYDR94WK9aUNsduaGoNmV4mtfhLLPRMkf2A2GzpTBfKjyypiojK,不知道怎么搞得编辑器里插入链接无法用,只能这样发了,懒得看的同学我就简单解释一下吧,其实看到处理后的数组大致也能明白,就是两头小,中间大,体现到坐标轴里的正态曲线呈钟型,两头低,中间高,左右对称因其曲线呈钟形,因此人们又经常称之为钟型曲线。
这道是面试的最后一题,做到这里的时候时间比较紧张了加上天气炎热口渴饥饿前台妹子太好看(别废话了就是因为算法弱。。。),稍作思考写了如下代码:
var arr = [1,2,1,3,3,2,4,6,3]
~(function(arr) {
var temp = [], i = 0, l = arr.length,
sortArr = arr.sort(function(a,b){return a-b}) //先将数组从小到大排列得到 [1, 1, 2, 2, 3, 3, 3, 4, 6]
for (;i<l;i++){
if(i%2==0){
temp[i/2] = sortArr[i] // 下标为偶数的顺序放到前边
} else {
temp[l-(i+1)/2] = sortArr[i] // 下标为奇数的从后往前放
}
}
console.log(temp) // [1, 2, 3, 3, 6, 4, 3, 2, 1] 看起来挺完美哈
})(arr)
由于是笔试,自己在脑海里边yy了一会程序后,觉得没啥大问题就交卷了,后来的面试官看了试卷,在面试过程中并没有提到这道题,所以觉得这种方法没什么问题了就没在面试过程中再问,不过来回来的路上,我突然想到了一个这样的情况:
var arr = [1,2,3,4,5,6,7,8,9] // 一个规则递增的数组
~(function(arr) {
var temp = [], i = 0, l = arr.length,
sortArr = arr.sort(function(a,b){return a-b}) for (;i<l;i++){
if(i%2==0){
temp[i/2] = sortArr[i]
} else {
temp[l-(i+1)/2] = sortArr[i]
}
} console.log(temp) //[1, 3, 5, 7, 9, 8, 6, 4, 2] 问题出现了。。
})(arr)
是的,这样一来这个数组的左右部分并不是对称的,以9为中心,左侧为1+3+5+7=16,右侧为2+4+6+8=20,明显的是左轻右重,不是一个均匀的正态分布了,随着数组的增大,带来的问题会越来越严重。
亚麻带。。。。我是一朵含苞欲放的花骨朵不要这样对我。。。
看来前边的代码是不能用的,只能重新思考解决方法,其实问题的核心在于保证数组的左右两侧是相等或者大致相等的,不管是奇数个数的数组还是偶数个数的,数组可以分为两部分(奇数个数的抛去最大值后也可以看做是一个偶数数组,即便有多个相同最大值也无所谓,从小到大排序后去除最后一个即可),还是按照上边的方法,下标为偶数的时候放到左侧,为奇数的时候放到右侧,在左右两边的数组增长过程中,当数组长度相等的时候,对左右两侧数组之和进行比较,因为是按照从小到大排列的,所以正常情况下,右侧会大于左侧,然后将右侧第一个跟左侧最后一个互换一下即可达到平衡的目的,代码如下:
var arr = [1,2,3,4,5,6,7,8,9],
sortArr = arr.sort(function(a,b){return a-b}),
l = arr.length,
temp_left = [], temp_right = [] function sort(arr){
var i = 0
for(;i<l;i++){
var eq = sortArr[i]
i%2 == 0 ? temp_left.push(eq) : temp_right.unshift(eq)
if(i > 1){
if( temp_left.length == temp_right.length && !compare(temp_left, temp_right)){
wrap(temp_left,temp_right) //数组相等并且右侧和大于左侧的时候进行交换
}
}
}
return temp_left.concat(temp_right)
} // 数组求和
function sum(arr) {
return eval(arr.join("+"));
} // 数组比较大小
function compare(arr1,arr2) {
return sum(arr1) >= sum(arr2)
} // 左边最后一个跟右边第一个交换 function wrap(l,r){
var m = r.shift()
r.unshift(l.pop())
l.push(m)
} console.log(sort(arr)) // 得到 [1, 4, 6, 7, 9, 8, 5, 3, 2]
这样一来整个正态分布就均匀多了,多做几组测试看看效果:
arr = [1,333,444,555,66,7788,909]
console.log(sort(arr)) /[1, 444, 909, 7788, 555, 333, 66] arr = [168.6,177.5,174.2,189.3,167.2,177.6,167.8,175.5]
console.log(sort(arr)) //[167.2, 174.2, 175.5, 189.3, 177.6, 177.5, 168.6, 167.8]
看起来还不错,在百度资料的过程中还查到一篇这样的文章,链接是 http://www.lai18.com/content/524601.html,貌似用c++完成的,不过看到文章最后的结果,并不是一个均匀的正态分布,倒是跟我第一个程序差不多,
本人不怎么会c++,也没运行多组结果看看,有兴趣的同学可以尝试下作为对比。
本文所有的程序我仅在chrome做过测试,如果其他浏览器有问题的话,希望留言告知,其实这东西也没什么难度,权当一个记录吧,有需要的时候可以用用。
关于javascript 数组的正态分布排序的一道面试题的更多相关文章
- javascript数组对象排序
javascript数组对象排序 JavaScript数组内置排序函数 javascript内置的sort函数是多种排序算法的集合 JavaScript实现多维数组.对象数组排序,其实用的就是原生的s ...
- 19 JavaScript数组 &数组增删&最值&排序&迭代
关联数组(散列) 关联数组又叫做散列,即使用命名索引. JavaScript数组只支持数字索引. JavaScript对象使用命名索引,而数组使用数字索引,JavaScript数组是特殊类型的对象. ...
- Javascript 迭代法实现数组多条件排序
多条件排序可能有很多种思路,效率也各不相同,我的方法可能只适合自己用,毕竟目的是为了实现功能,所以采用了最笨的方法,不过效果还是很理想的,经过多次测试,6列1000行数据,平均排序时间大约是:28ms ...
- Javascript 数组自定义排序,并获取排序后的保存原索引的同序数组(堆排序实现)
比如数组A: [ 0: 5, 1: 2, 2: 4, 3: 3, 4: 1 ] 排序后的结果为:[1, 2, 3, 4, 5],但是有时候会有需求想要保留排序前的位置到一个同位数组里,如前例则为:[4 ...
- JavaScript 数组、字符串、Map、Set 方法整理
在线阅读 https://www.kancloud.cn/chenmk/web-knowledges/1080519 数组 isArray():Array.isArray(value) 用于检测变量是 ...
- 教你用好 Javascript 数组
原文链接:https://juejin.im/post/5d9769b26fb9a04df26c1b89 作为 Javascript 的标准对象之一,数组是非常底层而且实用的数据结构.虽然结构很简单, ...
- Javascript数组操作
使用JS也算有段时日,然对于数组的使用,总局限于很初级水平,且每每使用总要查下API,或者写个小Demo测试下才算放心,一来二去,浪费不少时间:思虑下,堪能如此继续之?当狠心深学下方是正道. 原文链接 ...
- Javascript数组操作(转)
1.数组的创建 var arrayObj = new Array(); //创建一个数组 var arrayObj = new Array([size]); //创建一个数组并指定长度,注意不是上限, ...
- JavaScript 数组
JavaScript 数组 简介:数组是值的有序集合,JavaScript在同一个数组中可以存放多种类型的元素,而且是长度也是可以动态调整的,可以随着数据增加或减少自动对数组长度做更改. 一:创建数组 ...
随机推荐
- 0124——KVC KVO模式
1.KVC KVC是Key-Value-Coding的简称,它是一种可以直接通过字符串的名 字(key)来访问类属性(实例变量)的机制.而不是通过调用Setter.Getter方法访问.当使用KVO. ...
- css 梯形标签页
html 代码 略 css : nav > a{ position: relative; display: inline_block; padding: .3em 1em 0; } nav &g ...
- c++设计模式之策略模式
概念:通过定义一系列封装的算法,使得调度者可以互相替换,此模式让算法的变化,不会影响到使用算法的客户. 特点: 1)根据不同的情况创建不同的对象. 2)每个对象的方法名相同,但实现却不同. 结构: 1 ...
- stl学习之模板
模板是实现代码重用机制的一种工具,实质就是实现类型参数化,即把类型定义为参数. C++提供两种模板:函数模板,类模板. template<typename T> //或者 templa ...
- 从汇编看c++中含有虚基类对象的析构
c++中,当继承结构中含有虚基类时,在构造对象时编译器会通过将一个标志位置1(表示调用虚基类构造函数),或者置0(表示不调用虚基类构造函数)来防止重复构造虚基类子对象.如下图菱形结构所示: 当构造类B ...
- 层层递进Struts1(六)自定义转换器
Struts提供的类型转换有限,如果我们强行使用没有的类型转换,则会出现错误,以Date类型为例: org.apache.catalina.core.StandardWrapperValve invo ...
- JAVA不经过Catch(Exception e)直接到finally或者退出原因
今天遇到一个很奇葩的问题!在写Hadoop程序的时候!new一个对象!程序直接跑到finally代码块里面去了!Catch里面的Exception也没有执行. Configuration config ...
- 使用xml及java代码混合的方式来设置图形界面
参考<疯狂android讲义>第2版2.1节 设置android的图形界面有三种方法: 1.使用纯xml文件 2.使用纯java,代码臃肿复杂,不建议使用 3.使用xml与java混合,前 ...
- php的一些小笔记--字符串
字符串: 转换ASCII函数: ord($tring) 返回ASCII,chr($ASCII)返回相应的字符 把字符串切割成数据的函数: chunk_split($string,$len) chunk ...
- 磁盘管理三-raid
前言:何为raid raid是利用多个磁盘组成一个可提升效能.可包含冗余的磁盘阵列组.常用于数据吞吐量大(视频),冗余要求高的场景 当前raid包含了raid0-7,以及组合方式raid10,raid ...