关于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,明显的是左轻右重,不是一个均匀的正态分布了,随着数组的增大,带来的问题会越来越严重。

  亚麻带。。。。我是一朵含苞欲放的花骨朵不要这样对我。。。

  看来前边的代码是不能用的,只能重新思考解决方法,其实问题的核心在于保证数组的左右两侧是相等或者大致相等的,不管是奇数个数的数组还是偶数个数的,数组可以分为两部分(奇数个数的抛去最大值后也可以看做是一个偶数数组,即便有多个相同最大值也无所谓,从小到大排序后去除最后一个即可),还是按照上边的方法,下标为偶数的时候放到左侧,为奇数的时候放到右侧,在左右两边的数组增长过程中,当数组长度相等的时候,对左右两侧数组之和进行比较,因为是按照从小到大排列的,所以正常情况下,右侧会大于左侧,然后将右侧第一个跟左侧最后一个互换一下即可达到平衡的目的,代码如下:

 1 var arr = [1,2,3,4,5,6,7,8,9],
 2         sortArr = arr.sort(function(a,b){return a-b}),
 3         l = arr.length,
 4         temp_left = [], temp_right = []
 5
 6     function sort(arr){
 7         var i = 0
 8         for(;i<l;i++){
 9             var eq = sortArr[i]
10             i%2 == 0 ? temp_left.push(eq) : temp_right.unshift(eq)
11             if(i > 1){
12                 if( temp_left.length == temp_right.length && !compare(temp_left, temp_right)){
13                     wrap(temp_left,temp_right) //数组相等并且右侧和大于左侧的时候进行交换
14                 }
15             }
16         }
17         return temp_left.concat(temp_right)
18     }
19
20
21     // 数组求和
22     function sum(arr) {
23         return eval(arr.join("+"));
24     }
25
26     // 数组比较大小
27     function compare(arr1,arr2) {
28         return sum(arr1) >= sum(arr2)
29     }
30
31     // 左边最后一个跟右边第一个交换
32
33     function wrap(l,r){
34         var m = r.shift()
35         r.unshift(l.pop())
36         l.push(m)
37     }
38
39     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做过测试,如果其他浏览器有问题的话,希望留言告知,其实这东西也没什么难度,权当一个记录吧,有需要的时候可以用用。

时间: 2024-12-19 10:08:02

关于javascript 数组的正态分布排序的一道面试题的相关文章

javascript数组对象排序

javascript数组对象排序 JavaScript数组内置排序函数 javascript内置的sort函数是多种排序算法的集合 JavaScript实现多维数组.对象数组排序,其实用的就是原生的sort()方法,用于对数组的元素进行排序. sort() 方法用于对数组的元素进行排序.语法如下: ArrayObject.sort(order); 测试A: var mm=[1,4,0,6,3,1,2]; mm.sort(); alert(mm);//0 1 1 2 3 4 6 返回值为对数组的引

JavaScript基础之数组的重排序

JavaScript基础之数组的重排序 数组(Array)算是继Object之后我们最常用到的类型了.与其他语言不同的是,javascript数组的每一项可以保存任何类型的数据,并且数组的大小是可以动态调整的. JavaScript已经为我们提供了两个数组重排序的方法,reverse()和sort() 方法. 其中reverse()方法会反转数组项的顺序.举个栗子: var values = [18,4,56,1,"a","b","abc"];

Javascript 迭代法实现数组多条件排序

多条件排序可能有很多种思路,效率也各不相同,我的方法可能只适合自己用,毕竟目的是为了实现功能,所以采用了最笨的方法,不过效果还是很理想的,经过多次测试,6列1000行数据,平均排序时间大约是:28ms. 具体实现代码如下: function isArr(data) { return ({}).toString.call(data) == '[object Array]'; } function getIndex(arr) { var i = 0, len = arr.length keys =

JavaScript数组操作函数

1.concat() 连接两个或更多的数组 该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本.例如: <script type="text/javascript"> var arr = [1, 2, 3]; var arr1 = [11, 22, 33]; document.write(arr.concat(4, 5, arr1)); </script> 输出结果: 1,2,3,4,5,11,22,33 2.join() 把数组的所有元素放入一个字符串

js实现随机选取[10,100)中的10个整数,存入一个数组,并排序。 另考虑(10,100]和[10,100]两种情况。

1.js实现随机选取[10,100)中的10个整数,存入一个数组,并排序. 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Document</title> 6 </head> 7 <body> 8 <script type="text/java

JavaScript 数组去重

JavaScript 数组去重 Why underscore (觉得这部分眼熟的可以直接跳到下一段了...) 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. 阅读一些著名框架类库的源码,就好像和一个个大师对话,你会学到很多.为什么是 underscore?最主要的原因是 underscore 简短精悍(约 1.5k 行),封装了 100 多个有用的方法,耦合度低,非常适合逐个方法阅读,适合楼主这样的 JavaScript

javascript数组去重算法-----4(另一种写法)

1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>javascript数组去重算法-----3</title> 6 </head> 7 <body> 8 <script> 9 var arr = [1,1,2,2,3,2,2,3,3,1,1,4,4,5

JavaScript数组和字符串基础

数组的一些常用用法及练习 Array.concat( ) 连接数组 练习:    var arr=[1,2,3,4,5];     arr1=[7,8,9];     document.write(arr.concat(arr1[0]))//返回1,2,3,4,5,7 Array.join( ) 将数组元素连接起来以构建一个字符串  Array.length 数组的大小 Array.pop( ) 删除并返回数组的最后一个元素 练习:     var arr=[1,2,3,4,5]     doc

javascript数组去重算法-----4(另一种写法__2)

1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>javascript数组去重算法-----3</title> 6 </head> 7 <body> 8 <script> 9 var arr = [1,1,2,2,3,2,2,3,3,1,1,4,4,5