整理几个经典的算法,随时更新(排序,去重,斐波那契函数)

排序问题:
排序算法(Sorting algorithm)是计算机科学最古老、最基本的课题之一。要想成为合格的程序员,就必须理解和掌握各种排序算法。
目前,最常见的排序算法大概有七八种,其中"快速排序"(Quicksort)使用得最广泛,速度也较快。
思想:
(1)在数据集之中,选择一个元素作为"基准"(pivot)。
(2)所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边。
(3)对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。
    var quickSort = function(arr) {
      if (arr.length <= 1) { return arr; }
      var pivotIndex = Math.floor(arr.length / 2);
      var pivot = arr.splice(pivotIndex, 1)[0];
      var left = [];
      var right = [];
      for (var i = 0; i < arr.length; i++){
        if (arr[i] < pivot) {
          left.push(arr[i])
        } else {
          right.push(arr[i]);
        }
      }
      return quickSort(left).concat([pivot], quickSort(right));
    };








                                                                                                                                                         ——摘自阮一峰老师的:快速排序(Quicksort)的Javascript实现.
冒泡排序: 一次比较两个元素,如果它们的顺序错误就把它们交换过来。
function test1(arr){
for(var i =0;i<arr.length;i++){
for(var j =0;j<arr.length-1-i;j++){
var t ;
if(arr[j]>=arr[j+1]){

t = arr[j]; 

arr[j]=[j+1]; 

arr[j] = t;

//  ES6用解构赋值来交换两个值   [arr[j],arr[j+1]] = [arr[j+1],arr[j]]

}
}
return arr
 }


简单选择排序:每次循环找到最小的取出来,之后递归。
function test3(arr){
if(arr.length<=1){
return arr
}
var iMin = arr[0];
var index =0;
for(var i = 0;i<arr.length;i++){
if(arr[i]<iMin){
         iMin = arr[i]  ;        //每次循环找到最小的
index = i;
}
}
var aa = arr.splice(index,1);


return aa.concat( arguments.callee(arr))   //递归


}


去重:
对于数组去重,只要写过程序的,立刻就能得到第一个解法:
function unique(arr) {
  var ret = []
  for (var i = 0; i < arr.length; i++) {
    var item = arr[i]
    if (ret.indexOf(item) === -1) {
      ret.push(item)
    }
  }
                                                  
  return ret
}


上面这个函数很正确,性能也不错。但前端最大的悲哀也是挑战之处在于,要支持各种运行环境。在 IE6-8 下,数组的 indexOf 方法还不存在。直觉方案要稍微改造一下:
var indexOf = [].indexOf ?
    function(arr, item) {
      return arr.indexOf(item)
    } :
    function indexOf(arr, item) {
      for (var i = 0; i < arr.length; i++) {
        if (arr[i] === item) {
          return i
        }
      }
      return -1
    }




这里是封装一个array的一个indexOf方法
function unique(arr) {
  var ret = []


  for (var i = 0; i < arr.length; i++) {
    var item = arr[i]
    if (indexOf(ret, item) === -1) {
      ret.push(item)
    }
  }
  return ret
}


但是两层循环总是很不爽的。
第二种方法是我们利用json对象:
思路如下
1.创建一个新的数组存放结果;
2.创建一个空对象;
3.for循环时,每次取出一个元素与对象进行对比,如果这个元素不重复,则把它存放到结果数组中,同时把这个元素的内容作为对象的一个属性,并赋值为1,存入到第2步建立的对象中。
说明:至于如何对比,就是每次从原数组中取出一个元素,然后到对象中去访问这个属性,如果能访问到值,则说明重复。
Array.prototype.unique = function(){
 var res = [];
 var json = {};
 for(var i = 0; i < this.length; i++){
  if(!json[this[i]]){        res.push(this[i]);
   json[this[i]] = 1;
  }
 }
 return res;
}


但是这里判断1和“1”是相同的,这里修复下
------------------------------------------
functionunique(arr){
  varres=[]
  var json={}
 
  for(vari=0;i<arr.length;i++){
    varitem=arr[i]
    varkey=typeof(item)+item
    if(!json[key]){         
      res.push(item)
      json[key]=1
    }
  }
 
  return ret
}
当然这里面还可能有些问题,到时候根据实际项目来定

函数式编程:去重

        function test2(arr) {
            var json = {};
            return arr.filter(function(item,index,arr){
                if(!json[item]){
                    json[item] = 1;
                    return true
                }
            })
        }

ES6去重方法:

Set是一个类似数组对象,并且它的每个值都不相同;

Array.from() 可以将累数组对象和可遍历对象转换成真正的数组

      function u(arr) {
return Array.form(new Set(arr))
}


or
      function unique (arr) {
                  const seen = new Map()
     return arr.filter((a) => !seen.has(a) && seen.set(a, 1))
}




斐波那契数列 1 ,1,2,3,5,8,13,21          

方法1:递归
            
            function test(n) {
                if(n <= 2) {
                    return 1
                }
                return arguments.callee(n - 1) + arguments.callee(n - 2)  //利用递归
            }
            //        console.log(test(8))    //21
            
            function t(n) {
                var aaa = [];
                for(var i = 1; i <= n; i++) {
                    (function() {                                //外层这个闭包没必要,可以去掉
                        return  aaa.push(test(i))
                    })(i)    
                }
                return aaa
            }
            console.log(t(8))      //1 ,1,2,3,5,8,13,21



            方法二: 迭代
            
function aa(n){
                var num1 = 1;
                var num2 =1;
                var num3 =0;
                if(n<3){
                    num3 = 1
                }
                for( var i =3;i<=n;i++){
                    num3 = num1 +num2;
                    num1=num2;
                    num2 = num3        //当n=4时,这时候的num1的值是num2,num2的值是num3
                }
                return num3;
            }
           console.log(aaa(8))        //21
            function tt(n){
                var a = []
                for(var i = 1;i<=n;i++){
                    (function(){               //外层这个闭包没必要可以去掉
                        return a.push(aa(i))
                    })(i)
                }
                return a;
            }

            console.log(tt(8))    //1 ,1,2,3,5,8,13,21

方法三尾递归优化:

递归非常耗内存,因为需要同时保存成千上百个调用帧,很容易发生‘栈溢出’(stack overflow)。但对于尾递归优化来说,由于只存在一个调用帧,所以永远不会发生栈溢出。

function F(n,ac1 = 1,ac2 = 1){

if( n <=1 ){ return ac2}

return F(n - 1,ac2,ac1 +ac2)

}

尾递归的实现,往往需要改写递归函数,确保最后一步只调用自身。做到这一点的方法,就是把所有用到的内部变量改写成函数的参数.


方法四利用函数记忆功能

构造带记忆功能的函数。
var fibo = function(){
var memo = [1,1]; //存储我们的结果隐藏在闭包中,当调用的时候首先先检查这个结果是否存在了
var fib = function(n) {
var result = memo[n];
if(typeof result!== 'number') {
result = fib(n-1) + fib(n-2);
memo[n] = result
}
return result;
};
return fib
}()
最近看数据结构与算法发现第五种方法:动态规划,其实和记忆函数类似。
function febo(n){
var val = [];
for(var i = 0;i<=n;i++){
val[i] = 1;
}
for(var i = 2;i<=n;i++){
val[i] = val[i-1]+val[i-2]
}
return val[n-1]
}


  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值