最近看到了遇到面试题,内容是以最快的方法将一副扑克牌重洗?觉得挺有意思,总结了三种方法,下面的的代码是用js,呵呵,下面是代码。
function Shuffle() { this.arr=[]; //重整新排列数组 this.newArr=function () { this.arr=[]; for(var i=0;i<54000;i++){ this.arr.push(i); } }; //洗牌方法1 this.shuffle1=function () { var arr=this.arr; var len=arr.length/2; var arr1=arr.slice(0,len),arr2=arr.slice(len); var arr3=[],random,val1,val2; for(var j=len;j>0;j--){ random=Math.floor(j*Math.random()); val1=arr1.splice(random,1)[0]; val2=arr2.splice(random,1)[0]; arr3.push(val1,val2); } return arr3; }; //最简单粗暴的一种方法 this.shuffle2=function () { var arr3=[],arr=this.arr; var len=this.arr.length; for(var i=len;i>0;i--){ var random=Math.floor(Math.random()*i); arr3.push(arr.splice(random,1)[0]); } return arr3; }; //还有一种比较好的方法,这种方法的大概思路是54次循环,当循环到i位置时,次位置的元素就与它时候的任一元素元素位置 this.shuffle3=function () { var arr=this.arr; var val1,val2,random,len=this.arr.length; for(var i=0;i<len;i++){ val1=arr[i]; random=i+Math.floor(Math.random()*(len-i)); val2=arr[random]; arr[i]=val2; arr[random]=val1; }; return arr; } } var shuffle=new Shuffle(); // shuffle.newArr(); // console.time("1"); // shuffle.shuffle1(); // console.timeEnd("1"); // shuffle.newArr(); // console.time("2"); // shuffle.shuffle2(); // console.timeEnd("2"); // shuffle.newArr(); // console.time("3"); // shuffle.shuffle3(); // console.timeEnd("3");
当只有54张牌时这三种方法的运行时间相差无几,但是当54000时,差距就出来了,本来自己想的是第一种方法要少遍历一半的次数,结果还不如第三种快,比较疑惑,希望看到的大神指点;当长度是54000时这三种方法用的时间是 shuffle3<shuffle1<shuffle2,各位有什么更好的方法,欢迎留言评论。
补:第一种方法之所以慢是可能应为涉及到了太多的堆栈操作,需要不断地生成返回修改数组,涉及到多块内存操作,而第三种只是在重复操作一块内存,只是颠倒内存内的顺序。