JS常用算法

常用算法

1、累加/累积

一般形式:

累加:v += e

累积:v *= e

(v代表累加和/累积,e代表累加/累积项)

累加:将一系列的数据加到一个变量里面。最后得到累加的结果。

比如:将1到100的数求累加和。

var sum = 0;
for(var i=1; i<=100; i++){
    sum +=i;
}
alert(sum);//结果为:5050

累积:将一系列的数据乘积到一个变量里面,得到累积的结果。

常见的就是n的阶乘

var n = 100;
var result = 1;
for(var i=1; i<=n; i++){
    result *= i;
}
alert(result);

算法要点:

(1)初始化v,累加:v=0;累积:v=1;

e的初始化,如果累加/累积项比较复杂,可能会分解为几个子项分别初始化。比如计算圆周率的问题,累加项分解为符号、分子和分母三部分。

<script>
    /*
    * 1、写出代表数列的各个变量
    * 2、使用for循环,里面判断相加的次数
    * 3、数列的规律
    * 4、得出结论,输出结果
    * */
    var time = 1;//次数
    var deno = 2;//分母
    var member = 1;//分子
    var num = 0;
    var grade = member/deno;
    for(var time=1; time<=30; time++){
        num += grade;
        deno = deno + member;
        member = deno - member;
        grade = member/deno;
    }
    alert("数列和为:" + num);
</script>


(2)循环的控制条件

一种是固定次数,比如计算弹跳距离的问题。

var height = 100;
var num = -100;
for(var n=1; n<=10; n++){
    num += height*2;
    height = height/2;
}
alert("第10次反弹" + height/2 + "米。");
alert("第10次落地,共经过" + num + "米。");


次数不固定,而是要满足某个条件:计算圆周率问题要求最后一项的绝对值要小于10的负6次方。

(3)确定累加/累积项的变化

比如数列的前30项之和,是将当前的分子分母之和作为下一次的分母,当前的分母作为分子。

var time = 1;//次数
    var deno = 2;//分母
    var member = 1;//分子
    var num = 0;
    var grade = member/deno;
    for(var time=1; time<=30; time++){
        num += grade;
        deno = deno + member;
        member = deno - member;
        grade = member/deno;
    }
    alert("数列和为:" + num);


再比如求圆周率问题,是将符号取反、分母加2,然后得出下一项;

var x;
var y;
var sum = 0;
var area;
for(var n = 1; n <=1000000; n++){
    x = Math.random();
    y = Math.random();
    if((x*x) + (y*y) <= 1){
        sum++;
    }
}
area = (sum/1000000)*4;
alert(area);


2、迭代

迭代也叫辗转法。

规律:就是可以不断的用旧的值去得到新的值,直到我们想要得到的结果。

遇到迭代的问题怎样解决:

(1)找到迭代的变量(旧的值)

(2)确定迭代的关系

(3)知道想要的结果是什么(结束循环的条件)

       ①就是知道最终的结果

       ②循环的次数

案例:求两个数最大公约数
/*
* 1、接收用户输入的两个数
* 2、一个函数得到最大公约数
* 3、打印这个最大公约数*/
var num1 = Number(prompt("请输入一个数:"));
var num2 = Number(prompt("请输入一个数:"));
var result = GCD(num1,num2);
alert(result);

/*功能:得到这个最大公约数
* 函数名:GCD
* 参数:两个整数
* 返回值:最大公约数*/

/*具体实现思路:
* 1、如果num1<num2则交换,确保num1是较大的
* 2、计算余数
* 3、当余数不为0,重复步骤4-6
* 4、num2 => num1
* 5、余数 => num2
* 6、重新计算余数
* 7、最终得到最大公约数,也就是num2的值*/
方法一:
/*function GCD(num1,num2){
    var t ;
    if(num1%num2 == 0){
        return num2;
    }
    while(num1%num2 != 0){
        t = num1%num2;
        num1 = num2;
        num2 = t;
    }
    return t;
}*/
方法二:
/*具体实现思路详解代码*/
function GCD(num1,num2){
    if(num1 < num2){
        var t = num1;
        num1 = num2;
        num2 = t;
    }
    var remainder = num1%num2;
    while(remainder != 0){
        num1 = num2;
        num2 = remainder;
        remainder = num1%num2;
    }
    return num2;
}


3、递推

找到数学规律,通过公式计算到下一项的值,一直到我们要的结果为止。

案例:兔子产子:通过前两项得到下一项。

/*一般而言,兔子在出生两个月后,就有繁殖能力
* 一对兔子每个月能生出一对小兔子来
* 如果所有兔子都不死,那么一年以后总共有多少对兔子?*/

/*接收用户输入的月份
* 计算兔子的对数
*   (1)如果经过的月份小于2,那么兔子的对数为1
*   (2)否则 用初始的兔子的对数 加上 第一个月的对数 为第二个月兔子的对数
*       (an+1 = an + (an-1))
*    反复使用这个公式 计算出下个月兔子的对数一直到用户输入的月份为止
* 打印兔子的对数
* */
var month = Number(prompt("请输入月份:"));
/*第一种方案:*/
 var sum;
var an = 1;
var an_1 = 1;
if(month < 2){
    sum = 1;
}else{
    for(var i=1; i<month; i++){
        sum = an +an_1;
        an_1 = an;
        an = sum;
    }
}
alert(sum);

/*第二种方案:使用数组的方式*/
var rabbit = [1,1];
for(var m=2; m<=month; m++){
    rabbit[m] = rabbit[m-1]+rabbit[m-2];
}
alert(rabbit[month]);


递推分为顺推和逆推。

4、穷举

遇到一个问题找不到更好的解决方法(找不到数学公式或者规律)时,使用“最笨”的办法,利用计算机计算速度快的特点,将所有的可能性全部列举出来,并将我们想要得到的结果记录下来。

案例:求鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一。
百钱买百鸡,问鸡翁、鸡母、鸡雏各几何?

for(var cock=0; cock<=20; cock++){
    for(var hen=0; hen<=33; hen++){
        var chick = 100-cock-hen;
        if(100 == cock*5+hen*3+chick/3){
            document.write("鸡翁一共" + cock + "只;"+ "鸡母一共" + hen + "只;"+ "鸡雏一共" + chick + "只;"+ "<br>");
        }
    }
}


穷举方法的特点是算法,相应的程序也很简单,但计算量往往很大。但计算机的优势就是运算速度快,所以此算法可以扬长避短,往往可以取得不错的效果。

案例:有一个三位数,个位数字比百位数字大,而百位数字又比十位数字大,并且各位数字之和等于各位数字相乘之积,求此三位数。

/*思路:
* 对每一个三位数执行如下操作:
* 1、分解出个位、十位、百位
* 2、如果满足条件则输出
* */
for(var n=100; n<=999; n++){
    var b100 = Math.floor(n/100);
    var b10 = Math.floor((n%100)/10);
    var b1 = n%10;
    if(b1 <= b100){
        continue;
    }

    if(b100 <= b10){
        continue;
    }

    if(b1+b10+b100 != b1*b10*b100){
        continue;
    }
    document.write(n + "<br>");
}

/*思路2
* 分别取穷举百位十位和个位,将满足条件的进行输出*/

var count = 0;
for(var b1=2; b1<=9; b1++){
    for(var b100=1; b100<b1; b100++){
        for(var b10=0; b10<b100; b10++){
            count++;
            if(b1+b10+b100 == b1*b10*b100){
                var n = b100*100+b10*10+b1;
                document.write(n + "<br>");
            }
        }
    }
}
document.write(count);


5、递归

所谓递归,就是在函数内部又去调用自己。

案例1:求阶乘问题,在fact函数内部又去调用fact函数了

/*计算n的阶乘*/
function fact(n){
    if(1 == n){
        return 1;
    }
    return n*fact(n-1);
}
alert(fact(5));

递归算法如果按照常规思路去理解是非常复杂的,函数调用一层一层嵌套调用,然后一层一层返回。

递归实际上就是将规模为n的问题降阶为n-1的问题进行求解,也就是去找n和n-1之间的关系。

案例2:汉诺塔问题

/*汉诺塔问题
功能:将n个盘子从源柱,借助于辅助柱,到目标柱
* 输入参数:
*   n 盘子的个数
*   src 源柱
*   aux 辅助柱
*   dst 目标柱*/
function hanoi(n,src,aux,dst){
    if(1 == n){
        document.write(src + "→" + dst +"<br>");
    }else{
    hanoi(n-1,src,dst,aux);
    document.write(src + "→" + dst +"<br>");
    hanoi(n-1,aux,src,dst);
    }
}
hanoi(5,"A","B","C");

案例3:猴子选大王问题

/*猴子选大王问题
功能:计算n个猴子选大王的结果
* 输入参数:n 猴子的数量
* 返回结果:当选猴王的序号(从0开始)*/
function selectKing(n){
    if(1 == n){
        return 0;
    }
    return (selectKing(n-1)+3)%n;
}
var n = Number(prompt("请输入猴子的数量:"));
var selected = selectKing(n) +1;
document.write("恭喜" + selected + "号当选猴王!");

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值