JS常用算法-个人整理

自己整理的一些JS常用算法,有些是摘网上的,有些是自己整理的。

一、快速排序

思路

1.假设数组ary有n项, 取出其中的某一项p;
2. 定义两个空数组leftright,让p与数组其余项进行比对,小于p的pushleft,其余的pushright,并且让left数组位于p左侧,right位于p右侧;
3. 对leftright的项重复上诉1和2步骤,知道当leftright为空,最终获得p*n个数,并对p进行concat拼接,最终获得从小到大排序数组。
原理
根据《算法导论》快速排序中,当划分产生的两个子问题分别包括了n-1个元素和0个元素时,快速排序产生最坏情况发生,算法的复杂度是T(n)=O(n^2),在可能的最平衡的划分中,即其中一个子问题的规模为[n/2],而另外一个子问题的规模为[n/2]-1,这种情况下,快速排序的性能最好,算法的复杂度为T(n)=O(nlgn),事实上,任何一种常数比例的划分都会产生深度为O(lgn)的递归树,其中每一层的时间代价都是O(n),因此,只要划分是常数比例的,算法的运行时间总是O(nlgn);

  • 最坏情况公式:T(n)=T(n-1)+T(0)+O(n)=T(n-1)+O(n),每一层递归的代价可以被累加起来,从而算得T(n)=O(n^2);
  • 最好情况公式:T(n)=2T(n/2)+O(n),在上式中,我们忽略了一些余项以及减1操作的影响。最终递归式的解为T(n)=O(nlgn)
  • 平均的划分公式:T(n)=T(9n/10)+T(n/10)+cn这里,我们显式地写出了O(n)项中所隐含的常数c.由于递归树中,每层的代价都是cn,知道在深度log10n=O(lgn)达到递归的边界条件时为止,之后每层代价之多为cn。递归在深度为log10/9n=O(lgn)处为止,因此,快速排序的总代价为O(nlgn);
    伯乐在线 有篇文章这样描述他们http://blog.jobbole.com/100349/
    O()表示算法的时间复杂度,O(1)表示常数阶复杂度,O(n)表示线性阶复杂度,O(n^2)表示平方阶复杂度
    图片引用伯乐在线 - Panblack 翻译,黄利民 校稿
例子:

数据量低时,O(1) 和 O(n^2)的区别可以忽略不计。比如,你有个算法要处理2000条元素。

  • O(1) 算法会消耗 1 次运算
  • O(log(n)) 算法会消耗 7 次运算
  • O(n) 算法会消耗 2000 次运算
  • O(n*log(n)) 算法会消耗 14,000 次运算
  • O(n^2) 算法会消耗 4,000,000 次运算

看不懂,直接上代码

function qSort(ary) {
var left=[];//创建两个空数组
var right=[];

var p=ary[0]// 取出数组第一项

if(ary.length==0){//当数组长度为零时,返回空数组
return ary;
    }

for(var i=1;i<ary.length;i++){//用数组剩余值与第一个值做比较
if(p>ary[i]){
left.push(ary[i])
      }else{
right.push(ary[i])
      }
    }
return qSort(left).concat(p,qSort(right));
}
var ary=[1,2,3,2,22,11,32,54,3,232,4234,4,5]
console.log(qSort(ary));

二、冒泡排序

思路
1. 假设数组ary有n项;
2. 取出ary的第i项aryi,与其余项进行一一比较,如果小于则位置不变,大于则替换位置;
3. 重复上述2内容,同时,每遍历一次,与aryi比较数组项应-1;
4. 注意数组最后一项不需要进行比较。
原理

  • 根据《数据结构》严蔚敏版说解释:“起泡排序的过程,首先将第一个记录的关键字和第二个记录的关键字进行比较,若为逆,则将两个记录交换之,然后比较第二个记录和第三个记录的关键字,以此类推,知道第n-1个记录和第n个记录的关键字进行过比较为止。”
  • 也就说,假如有数组ary=[1,2,3,4,5],每比较一次,我们假设时间消耗是1.也就是ary的排序所消耗时间为:第一次比较4次,第二次比较3次,第三次比较2次,第四次比较1次,总计比较10次。
    当数组为ary=[1,2,3,4····,n-2,n-1,n];
第几次比较比较次数
1n-1
2n-2
3n-3
········
n-33
n-22
n-11

最终比较结果为O(n)=(n-1)+(n-2)+(n-3)+3+2+1=n*(n-1)/2.(数学公式:(首项+尾项)*项数/2)
也由于当n足够大时,得出总的时间复杂度为O(n^2)[忽略其他影响值比较小的数]

不明所以?上代码

 * @param ary 数组
 * @param type type表示升序(0)还是降序(1)
function sortAry(ary,type) {
for(var i=ary.length-1;i>0;i--){
  for(var j=0;j<i;j++){
    if(ary[j]>ary[j+1]){
      var temp=ary[j];
          ary[j]=ary[j+1];
          ary[j+1]=temp;
         }
      }
    }
 type===1?ary.reverse():void 0;
 return ary;
}
ary=[1,2,3,4,4,2,2,11];
console.log(sortAry(ary,0));

数组去重

方法一

思路
1. 在JS的对象类型中,每个属性名都是唯一的;
2. 同理,数组中的每一项,也是唯一的;
3. 如果让数组的每一项与值相等,即ary[i]=i,是否数组ary的所有值都会是唯一的?利用这个原理,就有了我们接下来的数组去重方法;
由于文字太绕,这里直接上代码

   function mySlice(ary) {
          var obj=[];
       for(var i=0;i<ary.length;i++){
           var cur=ary[i];
         if(obj[cur]==ary[i]){
            ary.splice(i,1);
              i--;//由于i从0开始,这里需要i--防止数组坍塌
         }else{
            obj[cur]=cur;
           }
         }
       }
      ary=[1,2,3,3,2,1,3,4,5,5,23,,4,4,,3,3];
      mySlice(ary);

方法二
思路
1. 与冒泡排序原理相同,假设数组ary有n项;
2. 取出ary的第i项aryi,与其余项进行一一比较,如果相等,删除该项,同时记得如果i从0开始,需要–i防止数组坍塌;

function mySlice(ary) {
   for(var i=0;i<ary.length-1;i++){
    for(var j=i+1;j<ary.length;j++){
      if(ary[i]==ary[j]){
        ary.splice(j,1);
             j--;
        }
      }
    }
 }
ary=[11,2,2,3,3,2,1,3,4,5,5,23,4,4,4,4,3,3];
mySlice(ary);

反转字符串

原网站:http://www.w3cplus.com/javascript/how-to-reverse-a-string-in-javascript-in-different-ways.html

  • 需求:假设有var str="abcdefg";将字符串str延中间字母左右调换位置,即调换后为str="efgdabc";

思路
1. 先判断字符串是奇数行还是偶数行;(这边分别使用两种字符串方法来操作)
2. 如果是奇数行,用Math.round(str.length/2)求出中间字符串的位置mid,用字符串方法substr(0,mid)substr(mid-1)分别将中间字符串左右两边的值分别取出,最后用concat重新拼接;
3. 如果是偶数行,我们统一取出中间两个字符串中的mid-right字符串,再用字符串方法split(mid-right)为中间为分界,拆分成数组,在用reverse进行数组倒序,最后用join拼接回字符串,加上mid-right即可

不知什么,直接看代码

function reversString(str) {
       var mid=(str.length%2==0);
       if(!mid){//奇数
           mid=Math.round(str.length/2);
           var arry1=str.substr(0,mid-1);
           var arry2=str.substr(mid);
           var arry3=str.charAt(mid-1);
           var arry=arry2.concat(arry3,arry1);
           return arry;
       }else{//偶数
           mid=str.charAt(str.length/2);
          var ary= str.split(mid);
           ary=ary.reverse();
           ary=ary.join("");
           ary=mid+ary;
           return ary;
       }
   }
   console.log(reversString("abcdefg"))

数组随机取整

案例原网站:http://www.w3cplus.com/javascript/rounding-recipes.html

/*思路:Math.random()函数经常返回0~1之间的浮点数。从技术上讲,Math.random()返回的数会出现0,但永远不会出现1
 *
 * */
 //从min-max里随机抽取6个不重复的整数,按从小到大输出(不包含min)                                                                                          //Math.ceil:向上取整
function random(min,max) {
         var a=[];
       while (a.length<6){
         var random=Math.ceil(Math.random()*(max-min))+min;
         var cur=random;
      if(a.indexOf(random)==-1){
             a.push(random);
        }
    }
     a.sort(function (a,b) {
       return a-b;
      })
       return a;
   }
console.log(random(0,33)) ;

Mutation

同样转载自w3cplus

//Mutations对一个包含两个元素的数组,检测数组中的第二个元素的所有字母是否都在第一个元素中出现过,如果出现true,否则false(忽略大小写)
//方法一:遍历
function mutation (arr) {
      var baseStr = arr[0].toLowerCase().split('');
      var testStr = arr[1].toLowerCase().split('');
    for (var i = 0, len = testStr.length; i < len; i++){
      var temp = baseStr.indexOf(testStr[i]);
      if (temp === -1) {
        return false;
        }
      }
        return true;
}
//方法二:every方法
function mutation (arr) {
     var baseStr = arr[0].toLowerCase().split(''),
     testStr = arr[1].toLowerCase().split('');
        return testStr.every(function (letter) {
          return baseStr.indexOf(letter) != -1;   });
    }

Falsey Bouncer

同样转载自w3cplus
1. falsy和truthy的概念:

  • falsy(既false值):false/null/undefined/NaN/0/”“(空字符串),其余都为truthy值
//通过JavaScript处理falsy值。创建一个bouncer(arr)函数,通过逻辑判断,删除数组中的falsy值.
 //完整版:
function bouncer (arr) {
  function isFalsy (value) {
    return Boolean(value);
     }
   var result = arr.filter(isFalsy);
   return result;
 }
//简略版
function bouncer(arr) {
   return arr.filter(Boolean);
 }
var arr=[null,1,2,"null",undefined,"1"]
console.log(bouncer(arr));-->[1, 2, "null", "1"]

从数组中寻找元素并删除元素

同样转载自w3cplus
1. 概念:有个数组ary=[[1,2,3,4,5,6,7,8],1,2];从中第一项单独与第二、三项分开来,并将第一项里面跟第二、三项值相同的数删除。
2. 实例

1. 利用push,分离原数组,然后用filter遍历原数组第一项,并过滤掉新数组中有同一项的值
function destroyer(arr) {
       var newArray = arguments[0]; // [1, 2, 1, 3, 2, 1, 3, 4, 2, 6]// 获取目标数组
       var removeArgs = []; // 声明一个空数组,用来存储需要从`newArray`中删除的元素
      for (var i = 1, len = arguments.length; i < len; i++) {
        removeArgs.push(arguments[i]);
        }
    function isFalse (value) {// 声明filter()方法的callback函数
        return removeArgs.indexOf(value) === -1;
        }
        return newArray.filter(isFalse);// newArray中删除1,2
  }
destroyer([1,2,1,3,2,1,3,4,2,6],1,2);
2. 第一步与方法一相同,只是后面一步用了一个判断,跟Mutation方法原理相同
function destroyer(arr) {
      var newArray = arguments[0]; //[1,2,1,3,2,1,3,4,2,6]
      var removeArgs = [];
    for (var i = 1, len = arguments.length; i < len; i++) 
    {             
    removeArgs.push(arguments[i]);
    }
    function isFalse (value) {
     for (var j = 0; j < removeArgs.length; j++) {
      if (removeArgs[j] == value) {
         return false;
            }
        } return true;
    }  
    return newArray.filter(isFalse); // 从newArray数组中删除1,2
}
3. 一种简化版
function destroyer(arr) {
     var removeArgs =Array.prototype.slice.call(arguments, 1); // [1, 2]
    // arr = [1, 2, 1, 3, 2, 1, 3, 4, 2, 6]
      return arr.filter(function(value) {
          return removeArgs.indexOf(value) < 0;
        });
    }
4. 利用套了两个for循环的遍历,将重复的项删除,同时注意防止数组坍塌
function destroyer(arr) {
   // arguments = [[1, 2, 1, 3, 2, 1, 3, 4, 2, 6],1,2]
    for (var i= 1; i< arguments.length; i++) {
      // arr = [1, 2, 1, 3, 2, 1, 3, 4, 2, 6]
     for (var j = 0; j < arr.length; j++) {
       if (arguments[i] == arr[j]) {
                arr.splice(j, 1);
                       --j;
             }
         }
      }
      return arr;
   }
5. 也是套用两个for循环的遍历,将重复的项删除,只是这里面的for循环是一个递减,所以不用考虑数组坍塌。
function destroyer(arr) {
    for (var i = 1; i < arguments.length; i++) {
     for (var j = arr.length - 1; j >= 0; j--) {
       if (arguments[i] == arr[j]) {
                arr.splice(j, 1);
            }
          }
       }
    return arr;
 }
6. ES6的 new Set方法和has方法
function destroyer(arr) {
      var removeArgs = new Set(Array.prototype.slice.call(arguments, 1)); //Set {1, 2}
    function isFalse (value) {
     return !removeArgs.has(value);
    }
    return arr.filter(isFalse);
 }
或者
function destroyer(arr, ...items) {
      var removeArgs = new Set(items); // Set {1, 2}
     function isFalse (value) {
      return !removeArgs.has(value);
    }
     return arr.filter(isFalse);
 }

以上内容,都是从其他地方摘取

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值