# JavaScript 流程控制语句 和 算法

TIP

本章节我们一起来学习流程控制语句,所谓的流程控制句语,就是指我们可以通过这些语句来控制代码按照什么样的顺序结构来执行。

在 JS 中流程控制主要有三种结构:顺序结构分支结构循环结构,这三种结构代表三种不同的代码执行顺序。

顺序结构:

代码默认执行结构就是按顺序结构,从上往下依次执行的。

分支结构语句

  • if 语句
  • switch 语句

循环结构的语句

  • for 语句
  • while 语句
  • do while 语句

这些都是接下来要学习的重点。首先我们来学习 if 语句

# 一、if 语句

TIP

if 语句是使用最频繁的语句之一,也是最简单的条件语句,也称为选择语句条件判断语句

# 1、最简单的 if 语句

TIP

  • if 是如果的意思,如果()括号中条件成立,则就执行{ }大括号中的语句块
  • 如果不成立,则啥也不做
if (条件) {
  // 当条件为真,则执行这里的代码
  // 语句块.....
}
// if语句后面的代码.....

注:

  • 这里的语句块可能是一行代码,也可能是一个多行代码
  • ()括号里的条件可以是任何任何表达式,并且求值结果不一定是布尔值
  • 但 JS 内部会自动调用Boolean()函数,将这个表达式的返回值转为 布尔值
  • 如果条件求值为true,则执行{}中的语句块,如果条件求值为false,则啥也不做。执行 if 语句后面的代码。

# 1.1、if 语句写法

<script>
  // 3>2 条件表达式,返回值为true
  if (3 > 2) {
    console.log(3 > 2); // true
  }
</script>
<script>
  // null 最终被转换成boolean值,是false,所以不会执行括号中的代码
  if (null) {
    alert("条件不足,我只能躲起来!");
  }
</script>

# 1.2、要注意区分那些是属于 if 语句体中的语句

<script>
  // ’‘ 最终被转换成boolean值,是false,所以不会执行括号中的代码
  if ("") {
    alert("条件不足,我只能躲起来!");
  }
  // 以下是if语句体外的代码,不管if中的条件是满足,他都会执行
  console.log("我和if没关系,我始终会执行");
</script>

# 1.3、 if 语句的简写

TIP

  • 如果 if 语句体中只有一条语句,可以省略大括号换行
  • 如果超过一条语句,是万万不能简写的,简写会造成编译错误。
<script>
  if (2 < 3) console.log("2<3成立,在控制台输出");
  if (2 > 3) console.log("2>3不成立,不在控制台输出");
  console.log("我与if无关,我永远出来");
</script>

# 2、if-else 语句

is-else

  • 如果条件求值为 true,则执行语句块 1 中的内容,否则执行语句块 2 中的内容
if (条件) {
  // 当条件为true,则执行这里代码
  // 语句块1....
} else {
  // 当条件为false,则执行这里代码
  // 语句块2....
}

代码演示:

var a = 3;
if (a > 2) {
  console.log(a + ">2"); // 输入3>2
} else {
  console.log(a + "<2");
}

# 案例实践:判断用户输入的数是偶数还是奇数

TIP

  • 如果一个数除以 2,能整除,也就是余数为 0,就是偶数,否则就是奇数
  • 但是如果用户啥也不输,''' '也会被转成 0,这里暂时不做讲解,下面案例中会完善
<script>
  // 弹出弹窗,让用户输入内容
  var num = Number(prompt("请用户输入一个数字"));
  // 上面num接收过来的值,是字符串类型,不过num%2时num会自动做隐式类型转换,转换成数字
  if (num % 2 == 0) {
    alert(num + "他是一个偶数");
  } else {
    alert(num + "他是一个奇数");
  }
</script>

# 3、if-else if 多条件分支语句

TIP

  • 如果条件 1 成立,则执行语句 1,后面的就不看了
  • 如果条件 1 不成立,则看条件 2,如果条件 2 成立,则执行语句 2,如果不成立,则执行语句 3
if (条件1) {
  // 条件2为真,执行这里的代码
  // 语句 1....
} else if (条件2) {
  // 条件1为假,条件2为真,执行这里代码
  // 语句 2....
} else {
  // 条件1和1都为假,执行这里代码
  // 语句2....
}

# 案例实践 1:根据用户的输入的成绩,判断用户是在那个成绩档次

分数 档次
90-100 优秀
89-70 良好
69-60 一般
0-59 不及格
<script>
  var score = prompt("请输入你的考试成绩!");
  if (score >= 90) {
    alert("成绩优秀");
  } else if (score >= 70) {
    alert("成绩良好");
  } else if (score >= 60) {
    alert("成绩及一般");
  } else {
    alert("成绩不及格");
  }
</script>

# 案例实践 2:判断用户输入的内容从是否为数字

代码实现思路分析:

  • 用户输入的内容,都是字符串,我们要判断是否为数字,肯定是要把类型转换数字,看能不能转成功。
  • 将字符串转成数字的方法有很多Number()parseInt()parseFloat()+号,我们选那个呢?
  • Number()+都可以,只要字符串是不是纯数字,都会转成NaN,纯数字符串都会转成数字,但' '空格不行,会被转成0
  • 所以接下来,接下来先过滤不是纯数字字符串,再过滤' ' 空格,剩下的就都是纯数字字符串了
  • 要判断 Number()函数转换后的结果是不 NaN 和数,有两种办法,
  • isNaN 用来判断一个数是不是数字,而 NaN 正好不是数字,还可以用 NaN 不自等的方法来判断。
  • 接下来要过滤' '' '空格 和 数字,可以通过 parseInt()和 isNaN 结合
  • 乘下的就都是 纯数字字符串了
<script>
  var num=prompt('请输入你的幸运数字!');
  if(isNaN(Number(num))){ // 如果条件成立,则num不是纯数字字符串,但不能过滤'' 空格
      console.log(num+'不是一个数字');
  }else if(isNaN(parseInt(num)){ // ’‘空格,会被转成NaN,NaN不是数字,为真,剩下的,就全都是纯数字了
           console.log(num +'不是一个数字');
  }else{
      console.log(num+'是一个纯数字');
  }
</script>
  • 封装成方法使用
function isNumber(num) {
  if (isNaN(+num)) {
    // 如果条件成立,则num不是纯数字字符串,但不能过滤'' 空格
    return false;
  } else if (isNaN(parseInt(num))) {
    // 识别空格或者没有输入任何值
    return false;
  } else {
    return true;
  }
}

# 4、if、if-else、if-else if 语句的嵌套

if(){
    // 语句 1
    // 语句中可以嵌套 if(){}else{ } 或if()else if(){}等if语句
}else{
    // 语句 2
    // 语句2中可以嵌套 if(){}else{ } 或if()else if(){}等if语句
}

# 5、if 嵌套案例实践

# 案例实践 1:BMI 肥胖指数计算

TIP

  • BMI 指数(Body Mass Index,身体质量指数)是用体重(以公斤为单位)除以身高(以米为单位)的平方得出的数字,是目前国际上常用的衡量人体胖瘦程度以及是否分赴康的标准。
  • BMI 指数 = 体重 / 身高 *身高
BMI 值 分档
低于 18.5 过瘦
18.5~24(不含) 正常
24~28(不含) 过胖
28~32(不含) 肥胖
大于等于 32 非常肥胖
<script>
  // 要求用户输入身高,强制转换为数字
  var height = parseFloat(prompt("请输入你的身高多少米"));
  // 要求用户输入体重
  var weight = parseFloat(prompt("请输入你的体重"));
  // 判断输入是否合法
  if (isNaN(height) || isNaN(weight)) {
    alert("你的输入有误!");
  } else {
    // 计算得到BMI指数
    var bmi = weight / (height * height);

    // 分档判断
    if (bmi < 18.5) {
      alert("偏瘦");
    } else if (bmi < 24) {
      alert("正常");
    } else if (bmi < 28) {
      alert("过胖");
    } else if (bmi < 32) {
      alert("肥胖");
    } else {
      alert("非常肥胖");
    }
  }
</script>

# 案例实践 2:判断用户输入的数是偶数还是奇数

<script>
  var num = prompt("请用户输入一个数字");
  if (isNumber(num)) {
    if (num % 2 === 0) {
      alert(num + "是一个偶数");
    } else {
      alert(num + "是一个奇数");
    }
  } else {
    alert("你的输入有误,请重新输入一次");
  }

  // 封装好的,用来判断用户输入的是否是纯数字
  function isNumber(num) {
    if (isNaN(+num)) {
      // 如果条件成立,则num不是纯数字字符串,但不能过滤'' 空格
      return false;
    } else if (isNaN(parseInt(num))) {
      // 识别空格或者没有输入任何值
      return false;
    } else {
      return true;
    }
  }
</script>

# 案例实践 3:游乐园门票计算

TIP

  • 某游乐园的门票价格如下表所示
  • 请用户输入年龄和星期几,弹出对话框显示门票价格
  • 星期日到星期一,分别用阿拉伯数字 0、1、2、3、4、5、6 表示
年龄大于 12 岁 年龄小于等于 12 岁
平日 100 50
周末 200 150

两种实现思路:

  • 左图:先判断星期几,再判断年龄
  • 右图:先判断年龄,再判断星期几

image-20220922161718954

<script>
  // 自动获取当前日期
  var date = new Date();
  // 设置日期 var date = new Date("2022/9/912");
  // 获取当前星期,0-6分别表示星期日-星期六
  var week = date.getDay();
  // 让用户输入年龄
  var age = Number(prompt("请输入你的年龄"));

  if (week == 0 || week == 6) {
    // 周末
    if (age > 12) {
      alert("周末门票价格" + 200);
    } else {
      alert("周末门票价格" + 150);
    }
  } else {
    // 平日
    if (age >= 12) {
      alert("今天门票价格" + 100);
    } else {
      alert("今天门票价格" + 50);
    }
  }
</script>

注:

在实际业务场景中,年龄也不会让用户自己输入,而是通过扫描身份证或输入身份证号来识别

身份证识别相关技术:

# 二、switch 语句

TIP

除 if 语句之外,JS 还提供了另外一种选择语句:switch 语句

switch (表示式或变量) {
  case1:
    // 执行语句1....
    break;
  case2:
    // 执行语句2....
    break;
  default:
    // 执行语句3....
    break;
}

# 1、switch 语句基本用法

TIP

swith 后面的表达式或变量依次会与case 后面的值进行比较,比较时是全等比较,因此不会做数据类型转换

  • 如果比较结果为 true,就会执行当前 case 下面的执行语句,执行到 break 关键字,就会跳出 switch 语句,退出执行。
  • 如果比较结果为 false,则继续往下比较,如果所有结果都为 false,则最后会执行 default 下面的语句。
  • 当然 default 也可以省略不写
<script>
  var a = 1; // a的类型是数字,这里可以尝试把值换成 1,3看下结果
  switch (a) {
    case "1": // 1 与 '1' 在全等比较时,返回false 不成立,则继续与下一个case后面值比较
      alert("这里是字符串1,匹配失败");
      break;
    case 2: // 1 与 2全等比较,false,继续往下比较
      alert("这里是2,匹配失败");
      break;
    case 1: // 1 与 1 全等,则执行这个case后面的语句
      alert("这里是1,匹配成功"); // 在页面弹出弹窗
      break;
    default:
      alert("找不到相匹配的内容");
      break;
  }
</script>

注:

以上代码最后执行结果,最后在页面弹出弹窗,弹窗内容为 '这里是 1,匹配成功'

在实际开发时,switch()括号中表达式的值,经常是以变量形式出现

# 2、break 不写会有什么影响

TIP

  • 如果不写 break,则会在匹配成功之后,后面所有 case 都将被视为匹配,直到遇见 break,才会退出。
  • 所有在 switch 语句中,程序员必须主动调用 break来跳出switch语句体
<script>
  var a = 1;
  switch (a) {
    case 0: // 全等匹配失败
      alert("这里是0,匹配成功"); // 这里不会弹出来
    case 1: // 全等匹配成功,下面代码会执行
      alert("这里是1,匹配成功"); // 这里会弹出来
    // 这个case中没有break,则会将后面所有case都被视为匹配,遇到break才退出
    case 2:
      alert("这里是字符串2,匹配成功"); // 这里会弹出来
      break; // 到这里退出
    case 3:
      alert("这里是字符串1,匹配成功");
    default:
      alert("找不到相匹配的内容");
      break;
  }
</script>

以上代码:

最后会在页面弹出 '这里是 1,匹配成功' ,确认后,又会接着弹出 '这里是字符串 2,匹配成功'

# 3、多条 case 共同一个语句体

TIP

switch 语句与 if 语的区别,switch 语句的用途:当一个变量被分类讨论的情形

  • 判断当前是休息日,还是工作日
  • 数字 0-6 表示星期日 - 星期六

if 语形式

<script>
  var week = 0;
  if (week == 1 || week == 2 || week == 3 || week == 4 || week == 5) {
    alert("现在是工作日,记得要早起喽!");
  } else if (week == 0 || week == 6) {
    alert("今天是周末,尽情的享受吧");
  }
</script>

switch 语句

<script>
  // week表时当前星期几
  var week = 4;
  // var week=new Date().getDay();   自动获取当天是星期几的方法
  switch (week) {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
      alert("现在是工作日,记得要早起喽!");
      break;
    case 6:
    case 0:
      alert("今天是周末,尽情的享受吧");
      break;
  }
</script>

# 4、switch 表达式值为布尔值

TIP

判断一个人是否是未成年人,如果满 18,就是成功,否则是未成年。

<script>
  var a = Number(prompt("请输入你的年龄!"));
  switch (true) {
    case a >= 18:
      alert("成年人");
      break;
    default:
      alert("未成年");
      break;
  }
</script>

# 5、switch 的嵌套

switch(){
    case1:
        // 执行语句
        break;
    case2:
        // 执行语句
        switch(){
            case1:
                // 执行语句
                break;
                // .....
        }
        break;
        // ......
}

# 6、switch 嵌套案例

TIP

案例实践:根据年份和对应的月份,判断月份天数

  • 1,3,5,7,8,10,12 月,每月 31 天
  • 4,6,9,11 月,每月 30 天
  • 当年为闰年 2 月 29 天,其它年份,2 月 28 天
<script>
  // var year=prompt('请输入当前年份')
  // var year=new Date().getFullYear(); 获取当前年份
  var year = 2022;
  // 用户输入月份
  var month = Number(prompt("请输出当前的月份"));
  // var month=new Date().getMonth()+1; 获取当前月份(new Date().getMonth()返回 0-11这间值,0代表1月)
  switch (month) {
    case 1:
    case 3:
    case 5:
    case 7:
    case 8:
    case 10:
    case 12:
      alert("当月有31天");
      break;
    case 4:
    case 6:
    case 9:
    case 11:
      alert("当月有30天");
      break;
    case 2:
      var isRunNian =
        (year % 4 == 0 && year % 100 != 0) ||
        (year % 100 == 0 && year % 400 == 0);
      switch (isRunNian) {
        case true:
          alert("这个月有29天");
          break;
        case false:
          alert("这个月有28天");
          break;
      }
      break;
    default:
      alert("你输入的月份有误!");
  }
</script>

# 7、if 语句和 switch 语句应用场景总结

条件判断句 应用场景
if 语句 根据条件做出判断,符合条件做什么,不符合条件做什么
switch 一个变量存在多个值的情况,根据不同的值来分别讨论时

# 三、for 循环

TIP

如果我们想在页面中,重复捃行某个操作时,我们就可以用到 for 循环语句。

  • 比如,你向一个女孩表白,他说,你必须要说 100 次"我爱你",她才答应做你女朋友,那怎么办呢 ?
  • 最简单的方式,就是把声音录到大喇叭里,重复的播放 100 次,哈哈!

我们来看下,如果没有 for 循环,拿之前学到的知识,我们要在页面输出 100 次"我爱你",要咱处理

<script>
  console.log("我爱你!");
  console.log("我爱你!");
  console.log("我爱你!");
  // ... 此处省略97次 console.log('我爱你!');
</script>
  • 但有了 for 循环,我们就可以简化程序的写法
<script>
  // 以下代码执行完,最后在控制台,输出100次“我爱你!”
  for (var i = 0; i < 100; i++) {
    console.log("我爱你!");
  }
</script>

# 1、for 语句的语法

TIP

首先我们来学习下 for 语句的语法,下面这个 for 循环语句有哪些组成部分

// 在控制台输出从0-9的数字
for (var i = 0; i < 10; i++) {
  console.log(i);
}

for 的圆括号中有三个表达式:

  • 表达式 var i=0;表示定义一个“循环变量"i,赋值为 0;
  • 表达式 i < 10; 表示继续执行循环的条件,只要这个条件为真,则会一直执行;
  • 表达式 i++ 用来更新循环变量,使循环变量的值越来越趋向终点

# 2、for 语句的执行机理

TIP

我们先来看一个简单的 for 循环语句:

image-20220910162136307

  • 首先会执行语句 ①
  • 然后判断语句 ②是否满足,如果满足则进入循环体,执行语句 ③,如果不满足则退出循环
  • 语句体中的语句执行完毕后,执行语句 ④
  • 再次判断语句 ②是否满足,如果满足则进入循环体,执行语句 ③,如果不满足则退出循环
  • ...... 依次继续循环执行

image-20220910231817112

# 3、准确遍历 for 循环

TIP

根据 for 循环执行机理,必须要会准确遍历 for 循环

案例 1:

for (var i = 3; i <= 15; i += 3) {
  console.log(i); // 3,6,9,12,15
}

/*
    当 i=3, 3<=15, 满足条件,输出 3; 再执行i+=3更新循环变量,得到i=6
    再次判断 i<15这个条件, 即 6<=15, 满足条件,输出 6;  再执行i+=3更新循环变量, 得到i=9
    再次判断 i<15这个条件,即 9<=15, 满足条件,输出9; 再执行i+=3更新循环变量,得到 i=12
    再次判断 i<15这个条件,即 12<=15, 满足条件,输出12; 再执行i+=3更新循环变量,得到 i=15
    再次判断 i<15这个条件,即 15<=15, 满足条件,输出15; 再执行i+=3更新循环变量,得到 i=18
    再次判断 i<15这个条件,即 18<=15, 不满足条件,退出for循环
*/

案例2:

for (var i = 15; i > 2; i -= 3) {
  console.log(i); // 15,12,9,6,3
}

/*
    当 i=15, i>2, 满足条件,输出 15; i-=3 得到 i=12
    当 i=12, i>2, 满足条件,输出 12; i-=3 得到 i=9
    当 i=9, i>2, 满足条件,输出 9; i-=3 得到 i=6
    当 i=6, i>2, 满足条件,输出 6; i-=3 得到 i=3
    当 i=3, i>2, 满足条件,输出 3; i-=3 得到 i=0
    当 i=0, i>2, 不满足条件,退出循环
*/

案例 3:

for (var i = 2; i < 12; i += 3) {
  i += 4;
  console.log(i); // 6,13
}

/*
  当 i=2, i<12, 满足条件,i+=4, 输出 6; 再执行i+=3 得到 i=9
  当 i=9, i<12, 满足条件,i+=4, 输出 13; 再执行 i+=3 得到 i=16
  当 i=16, i<12, 不满足条件,退出循环
*/

案例 4:

for (var i = 1; i < 10; i++) {}
// 不在循环体中,输出循环体结束时 i 的值
console.log(i); // 10

案例 5:

for (var i = 1; i < 10; i--) {
  console.log(i); // i永远都会小于10 ,所以会进入死循环
}

案例 6:

for (var i = 10; i < 4; i++) {
  console.log(i); // 没有任何输出,一开始就不满足条件
}
// 在循环体外输出:i=10
console.log(i);

# 4、for 循环案例

  • 求 1-10 之间所有数字之和
// 这里一定要赋初始值为0,否则为undefined,在做+加法运算时,转换成NaN,NaN与任何数相加都得NaN
var sum = 0;
for (var i = 1; i <= 10; i++) {
  sum += i; // 等同于 sum=sum+i;
}
console.log(sum); // 55
  • 字符串的拼接(在页面输入 10 颗星星)
// 一定要赋初值始,并且只能是''字符符串。
var str = "";
for (var i = 0; i < 10; i++) {
  str += "★";
}
console.log(str); // ★★★★★★★★★★

# 5、for 循环嵌套

TIP

for 循环中可以嵌套 for 循环

for (var i = 0; i < 5; i++) {
  // ...循环体
  for (var j = 0; j < 5; j++) {
    // ...循环体
  }
}

for 循环嵌套的执行原理

  • 从最外层 for 循环开始执行,执行到内部 for 循环时,要把内部 for 循环执行完
  • 再更新最外层的循环变量,然后判条件是否成立,成立则执行循环体中代码,进入内部循环
  • 内部循环全部执行完,再更新最外层循还变量......重复上面过程
for (var i = 1; i <= 3; i++) {
  for (var j = 1; j <= 5; j++) {
    console.log("i=" + i + ",j=" + j);
  }
}
/*
 * 首先i=1,i<=3成立,则进入循环体,执行循环体中的for
 * j=1,j<=5成立,则进入循环体,执行循环体中的代码  console.log("i=" + i + ",j=" + j);
 * 执行成功后,j++,得到j=2,再判2<=5成立,则再执行循环体中代码
 * 重复上面过程,当j的值为6时,退出第二个for循环体。进入第一个for循环,i++得到i=2,2<3成立,
 * 进入第二个for循环,首先j=1,1<5成立,则进入第二个for循环体......
 * 最后当i=4是,退出整个for循环。
 */

image-20220910165157209

# 6、for 循环嵌套案例

# 案例实践 1:打印如下图形

题目要求

理解最外层 for 循环代表行,最内层 for 循环代表列

image-20220910235506744

var str = "";
// 行
for (var i = 0; i < 5; i++) {
  // 列
  for (var j = 0; j < 7; j++) {
    str += "★";
  }
  str += "\n";
}
console.log(str);

# 案例实践 2:打印 99 乘法表

题目要求

  • 在理解理解最外层 for 循环代表行,最内层 for 循环代表列的基础上
  • 要找出行与列对应的关系(这是最难,也是必需要攻克的)

document.write()把内容添加到htmlbody标签中

<style>
  span {
    display: inline-block;
    width: 100px;
    line-height: 30px;
    background-color: #ddd;
    margin: 5px;
    text-align: center;
  }
</style>
<script>
  // 最外层for循环打印对应行数
  for (var i = 1; i <= 9; i++) {
    // 内层for循环,打印对应列数
    for (var j = 1; j <= i; j++) {
      document.write("<span>" + j + "*" + i + "=" + j * i + "</span>");
    }
    document.write("<br/>");
  }
</script>

image-20220910195059184

总结规律:

  • 最外层 for 循环对应的行数
  • 最内层 for 循环对应每一行中的列
  • 在执行 for 嵌套时,首先要找的就是行和列的关系(当然最难的也就是找出列和行之间的关系)

有了这个规律,我们想打印任何图形,就变的轻松简单了。我们来看下面这几个图形可以如何打印

# 案例实践 3:打印下表中的 3 个图形

题目要求

document.writeln 是向文档中写入一串文本,并紧跟着一个换行符(换行符会被编译成空格效果)

等腰三角形 V 字形 X 图形
image-20220910184848073 image-20220910191453839 image-20220910193725282
  • 图形打印原理

image-20220923193546683

  • 等腰三角形
<script>
  // 行
  for (var i = 0; i <= 5; i++) {
    // 列左边空格
    for (var j = 1; j <= 5 - i; j++) {
      document.writeln("&nbsp");
    }
    // 列中口
    for (var k = 0; k < i + 1; k++) {
      document.writeln("口");
    }
    document.writeln("</br>");
  }
</script>
  • V 字形
<script>
  // 图形行
  for (var i = 0; i <= 5; i++) {
    // 列前面空格
    for (var j = 0; j < i; j++) {
      document.writeln("&nbsp;");
    }
    // 列中第1个星星
    for (var k = 0; k <= 0; k++) {
      document.writeln("*");
    }
    // 每列两个星星中间的列空格
    for (var h = 0; h < 9-2*i; h++) {
      document.writeln("&nbsp;");
    }
    // 列中第2个星星
    for (var k = 0; k <= 0; k++) {
      if (i != 5) {
        document.writeln("*");
      }
    }
    document.writeln("</br>");
  }
</script>
  • X 图形
<script>
  // 打印 x的上半部分
  for (var i = 0; i <= 5; i++) {
    // 列前面空格
    for (var j = 0; j < i; j++) {
      document.writeln("&nbsp;");
    }
    // 列中第1个星星
    for (var k = 0; k <= 0; k++) {
      document.writeln("*");
    }
    // 每列两个星星中间的列空格
    for (var h = 0; h < 9-2*i; h++) {
      document.writeln("&nbsp;");
    }
    // 列中第2个星星
    for (var k = 0; k <= 0; k++) {
      if (i != 5) {
        // 在v的底部,只要一个星,所以要去掉一个
        document.writeln("*");
      }
    }
    document.writeln("</br>");
  }
  // x的下半部分
  for (var i = 0; i <= 5; i++) {
    // 列前面空格
    for (var j = 0; j < 4 - i; j++) {
      document.writeln("&nbsp;");
    }
    // 列中第1个星星
    for (var k = 0; k <= 0; k++) {
      // 保证上v和下v中*的个数相同,则下v左边最后一个星要去掉
      if (i != 5) {
        document.writeln("*");
      }
    }
    // 每列两个星星中间的列空格
    for (var h = 0; h <= i * 2; h++) {
      document.writeln("&nbsp;");
    }
    // 列中第2个星星
    for (var k = 0; k <= 0; k++) {
      if (i != 5) {
        document.writeln("*");
      }
    }
    document.writeln("</br>");
  }
</script>

# 四、for 循环算法题

TIP

关于什么是算法,我们先不讲,我们做两道算法题,来找找感觉,然后在本章的第九个版块,我们会再深入探讨算法。

在接下来的算法题中,我们会接触 2 个重要的概念:累加器累乘器

# 1 、计算 1+2+3+ ...... +99+100 的和

题目解析

求 1+2+3+.....+99+100 的和,本质就是等差数列求和

什么是等差数列 ?

  • 等差数列:如果一个数列从第二项起,每一项与它的前一项的差等于同一个常数,这个数列就叫做等差数列
  • 如:1,2,3,4,5,6..... 或 1,3,5,7,9,11,....
  • 如果我们要计算等差数列的求和,在数学中是有计算公式的,也就是前面讲到的高斯算法:
  • 计算等差数列前 n 项和:Sn=(n*(a1+an))/2
  • a1代表首项,a2 代表第 2 项.....an 代表第 n 项

注:

  • 在计算机中,并没有等差数的求和公式,我们必须一项一项的加起来,就要用到 for 循环
  • 在 JS 中,我们使用累加器来操作
// 创建累加器
var sum = 0;
// 遍历1到100的每一个数字,每遍历一个数字就要把这个数字加到sum中去
for (var i = 1; i <= 100; i++) {
  sum += i;
}
// 输出累加器的值
console.log(sum);

注意:

  • 累加器(变量 sum)必须定义在循环外面的前面
  • 累加器的初始值必须设置,而且必须设置为 0,不会影响累加结果
  • 使用最终累加结果时,必须在 for 循环结束后的外面
  • 很多 JS 大神喜欢将 sum 这样的变量,书写在 for 循环的括号中
// 循环开始的时候定义sum,sum就是累加器,初始值是0
// 遍历1到100的每一个数字,每遍历一个数字要把这个数字加到sum中去
for (var i = 1, sum = 0; i <= 100; i++) {
  sum += i;
}
// 输出累加器的值
console.log(sum);

# 2、计算 10 的阶乘

题目解析

  • 一个正整数的阶乘factorial)是所有小于及等于该数的正整数的积,并且 0 的阶乘为 1。
  • 自然数 n 的阶乘写作 n!
  • 10! = 10 _ 9 _ 8 _ 7 _ 6 _5 _ 4 _ 3 _ 2 *1
  • 在 JS 中,我们使用累乘器来操作
<script>
    // 累乘器,初始值必须是1
    var n = 1;
    for (var i = 10; i >= 1; i--){
        // 将每一次的数据 i 要累乘到 n 中去
        n *= i;
    }
    // 循环结束后使用累乘结果
    console.log(n); // 3628800
</script>

注:

  • 累乘器必须定义在循环外部前面
  • 累乘器的初始值必须是 1,因为 1 乘以任何数都等于本身
  • 累乘器最终结果必须在 for 循环结束后的外面

# 五、while 循环

TIP

while 表示 "当" 的意思,是一种先测试语句,和 for 循环一样,先测试条件,根据测试条件再判断是否执行行环循体中代码

while (测试条件) {
  // 执行语句,代码块
}
var i = 1; // 循环变量
while (i < 10) {
  // 测试条件
  // 循环体
  console.log(i);
  i++; // 更新循环变量
}

image-20220910231920887

# 1、while 循环注意事项

注:

  • while 语句事先不指定循环开始、结束的范围,只要测试条件满足,就一直执行循环体
  • 所以 while 循环体内的语句,必须使循环测试条件趋向不成立,否则会死循环
  • while 循环没有指定循环的变量,必顺在循环外定义好循环的变量
var i = 0; // 定义循环变量
var num = 0; // 累加器
while (i <= 10) {
  // 测试条件
  num += i;
  i++; // 更新循环变量
}

# 2、更适合 while 的应用场景

TIP

while 循环更适合,没有定范围的循环,根据结果,找条件。

# 应用实践 1:寻找 n2大于 23450 的最小整数

var n = 1;
while (n * n <= 23450) {
  n++;
}
console.log(n); // 154

# 应用实践 2:

小兔子拔萝卜,第 1 天拔 1 个,第 2 天拔 2 个,第 3 天拔 3 个 .... 以此类推。请问小兔子多少天能把 500 个萝卜扒光 ?

题目解析:

我们把这个题转化成下面这个表格,大家没有没发现,这是不是我们前面讲过的等差数列的求和。

第 1 天 第 2 天 第 3 天 ..... 第 n-1 天 第 n 天
1 2 3 ..... n-1 n
  • 当等差数列 1,2,3,4....n-1,n 之和第一次>500 时,这里的 n 就是我们要找的 n
  • 所以我们需要有一个累加器来累加所有天数萝卜之和,当累加器的值<500 时,就一直累加,加到>500 时,就不加了。
var n = 1; // 天数,也是这一天的拔萝卜数
var sum = 0; // 累加器
while (sum < 500) {
  sum += n;
  n++; // 最后一次循环会多加一个1
}
console.log(n - 1); // 32

验证:

通过等差数列求和公式: (首项 + 末项) * 项数 / 2 = 和

  • 计算 1+2+3+4+5 ... +32 的和
  • (1 +32) * 32 / 2 = 528

# 六、do while 循环

image-20220910231947027

详细解读

  • do while 循环是一种 后测试循环语句,这一点和 while 和 for 都不一样。
  • for 循环和 while 循环每次都是 "先测试条件是否满足,然后执行循环体"
  • do while 循环是 "先执行循环,然后测试条件是否满足"
do {
  // 循环体
} while (循环执行条件);
  • 循环体一定会至少执行一次,然后再检测循环执行条件是否为 true,决定是否继续执行循环体。
  • do while 循环将循环执行条件写到了循环体的后面
// do while循环是后判断的循环形式,能至少执行一次循环体
do {
  console.log("太棒了!");
} while (false);

# 1、随机数函数

TIP

  • 在接下来的案例中,我们会用到随机函数,所以在此我们先来学习下随机数函数
  • Math.random()方法,可以得到 0-1 之间的小数
Math.random(); // 输出0~1之间的随机数

image-20211218223539723

  • 得到 [a , b] 区间的整数,公式如下
parseInt(Math.random() * (b - a + 1)) + a;
  • 得到[1 ,5]区间的整数
parseInt(Math.random() * 5) + 1;

image-20211218224225733

  • 得到[5 ,15]区间的整数
parseInt(Math.random() * 11) + 5;

image-20220910214116295

# 2、更适合 do while 的应用场景

TIP

  • 先运行一次代码,如果不符合条件再重做,符合就不做了。
  • 其不满足条件,是在事情做完后产生的

# 应用实践 1:

随机生成 2 个 1-10 之内的整数,但是这 2 个数之和要等于 10

<script>
  var a, b;
  do {
    a = parseInt(Math.random() * 10) + 1;
    b = parseInt(Math.random() * 10) + 1;
  } while (a + b != 10);
  console.log(a, b);
</script>

# 应用实践 2:

随机移动元素的位置

题目解析

  • 在做游戏开发和动画的时候,我们想随机生成两个数 a 和 b,作为元素在 x,y 轴方向上的移动距离
  • 要求 a 和 b 的值均在[-10 , 10]区间随机整数
  • 但 a 和 b,不能同时为 0
var x, y;
do {
  x = parseInt(Math.random() * 21) - 10;
  y = parseInt(Math.random() * 21) - 10;
} while (x == 0 && y == 0);
console.log(x, y);

# 七、break、continue、label 语句

TIP

break 和 continue 语句为执行循环代码提供了更严格的控制手段

# 1、break 语句

什么时候用 ?

break 语句用于立即退出当前循环,他只能用在循环语句中,如 for 循环和 while 循环中都可以

for (var i = 0; i < 10; i++) {
  console.log(i);
  if (i == 5) {
    break;
  }
}
// 输出:0、1、2、3、4、5
// 当执行到i==5时,遇到break,就会退出整个循环语句
  • break 在 for 嵌套中,他只会退出他所在的那个 for 循环语句,然后继续执行当前 for 循环外的 for 循环体中语句
<script>
  for (var i = 0; i < 4; i++) {
    for (var j = 0; j < 4; j++) {
      if (j == 3) {
        break; // 每次执行到j==3时,就会退出当前for循环,继续执行当前for外的for循环
      }
      console.log(i + "-" + j);
    }
    console.log("j" + j); // break退出for时,会从这里开始执行下一次的外层for循环
  }
</script>

image-20220911202703554

  • break 用在 while 语句中,通常和while(true){}搭配使用
// 寻找最小的满足 n^2 > 456789 的整数n
// 方法一
var n = 1;
while (n * n <= 23450) {
  n++;
}
console.log(n); //154

// 方法二
var n = 1;
while (true) {
  if (n * n > 23450) {
    break;
  }
  n++;
}
// 输出:154

# 2、continue 语句

TIP

continue 用于跳过循环中的一个迭代 ,并继续执行循环中的下一个迭代,for 循环更经常使用 continue

for (var i = 0; i < 10; i++) {
  if (i == 5) {
    continue;
  }
  console.log(i); // 0、1、2、4
}
  • continue 在 for 嵌套中,也是跳过当前循环中的一个迭代,并继续执行循环中的下一个迭代
<script>
  for (var i = 0; i < 4; i++) {
    for (var j = 0; j < 4; j++) {
      if (j == 2) {
        continue;
      }
      console.log(i + "-" + j);
    }
  }
</script>

image-20220911202840093

# 3、label 语句

TIP

我们上面讲过,不管是 continue 还是 break,他最多能退出的也就是当前的 for 循环,如果我想退出最外层的 for 循环,那就可以借助这里的 label

在实际开发应用不多,了解即可

label: statement
  • label 表示标签名,这个名字是可以自定义的标识符
  • statement 表示代码块
  • label 标签名和 statement 代码块之间使用英文状态下的冒号分隔
  • label 标签一般都是与 for 循环语句等循环语句配合使用,同时是由 break 和 continue 语句引用的。

# label 标签与 continue 语句结合

两者结合

表示退出到 label 标记位置,继续从 label 标签标识的 for 循环开如执行下一次循环

// outer就是label标签,用来标识第一个for循环语句,其名字outer可以自定义,不一定是outer
outer: for (var i = 0; i < 4; i++) {
  for (var j = 0; j < 4; j++) {
    if (j == 2) {
      continue outer;
    }
    console.log(i + "-" + j);
  }
  console.log("j" + j); // continue outer退出时,不会执行这个代码
}

image-20220911203813270

这里要特别注意区分和 break 的区别,break 是退出当前 for 循环,会从 for 循环的外层循环语句体开始执行

// outer就是label标签,用来标识第一个for循环语句,其名字outer可以自定义,不一定是outer
for (var i = 0; i < 4; i++) {
  for (var j = 0; j < 4; j++) {
    if (j == 2) {
      break;
    }
    console.log(i + "-" + j);
  }
  console.log("j" + j); // break退出后,会执行这个代码
}

image-20220911203843314

# label 标签与 break 语句结合

两者结合

表示立即退出到 label 标签标识后的 for 循环,不再执行

// outer就是label标签,其名字可以自定义,不一定是outer
outer: for (var i = 0; i < 4; i++) {
  for (var j = 0; j < 4; j++) {
    if (j == 2) {
      break outer;
    }
    console.log(i + "-" + j);
  }
  console.log("j" + j); // 永远不会执行
}

image-20220910231242186

# 4、关于break、continue、label语句总结

语句 描述
break break语句用于立即退出当前循环,他只能用在循环语句中,如for循环和while循环中都可以
continue continue 用于跳过循环中的一个迭代 ,并继续执行循环中的下一个迭代
label 与break配合:表示立即退出到label标签标识后的for循环,不再执行
与continue配合:表示退出到label标记位置,继续从label标签标识的for循环开始执行下一次循环

# 八、循环语句总结

循环类型 语法 使用场景
for 循环 for(语句 1; 语句 2; 语句 3) {
被执行的代码块;
}
循环次数是固定的,知道明确的循环范围
while 循环 while(条件){
需要执行的代码;
变量变化语句;
}
循环次数不定,更适合根据结果,找条件
do ... while 循环 do {
需要执行的代码;
} while(条件)
先运行一次代码,如果不符合条件再重做,符合就不做了。
其不满足条件,是在事情做完后产生的。

# 九、重难点总结

TIP

总结本章重难点知识,理清思路,把握重难点。并能轻松回答以下问题,说明自己就真正的掌握了。

用于故而知新,快速复习。

# 1、重点内容

# ①、JavaScript中的流程控制语句有哪些 ?

TIP

  • 分支结构语句

    • if 语句
    • switch 语句
  • 循环结构的语句

    • for 语句
    • while 语句
    • do while 语句
  • 其它语句

    • break 退出当前循环
    • continue 跳过当前迭代,继续执行下一个迭代
    • label 给语句加标签,常合for嵌套循环一起使用

# ②、if 多分支语句的执行机理,for循环的执行机理

if执行机理

ifelse

for环循还执行机理

for环循还执行机理

# ③、for 和 while、do while循环各有什么应用场景 ?

循环语句 应用场景
for 循环 for 循环次数是固定的,知道明确的循环范围
while 循环 循环次数不定,更适合根据结果,找条件
do while 循环 先运行一次代码,如果不符合条件再重做,符合就不做了。

# ④、for循环打印图形规律 ?

  • 外层for循环控制行
  • 内层for循环控制列

# ⑤、break、continue、label的用法

语句 描述
break break语句用于立即退出当前循环,他只能用在循环语句中,如for循环和while循环中都可以
continue continue 用于跳过循环中的一个迭代 ,并继续执行循环中的下一个迭代
label 与break配合:表示立即退出到label标签标识后的for循环,不再执行
与continue配合:表示退出到label标记位置,继续从label标签标识的for循环开始执行下一次循环

# 2、难点内容

TIP

  • 1、for、while、do..while的应用场景
  • 2、for循环的应用案例

# 十、作业

1、下面代码的运行结果是 ?

var str = "icoding123";
var num = parseInt(str);
if (num == NaN) {
    alert(NaN);
} else {
    alert(str);
}
var a = 1;
var b = 0;
var str1 = "";
var str2 = false;
if (a || b || str1) {
    alert(a + b + str1);
}
if (a && b && !str2) {
    alert(!str2);
}
if (a && !str1 && !str2) {
    alert(!str1);
}

2、完整课程中讲到的所有案例

# 十一、算法

接下来,我们来学习算法,算法是大厂面试必考点 !了解算法是非常非常有必要的。

首先我们来了解下什么是算法(Algorithm)?

这里我们从一个算法的小故事开始切入

有一个“熊孩子”,小时候非常淘气,一次数学课上,老师为了让他们安静下来,给他们列了一道很难的算式,让他们一个小时内算出1+2+3+4+5+6+……+100的得数。

作为我们正常的一般思维,我们会如何计算呢 ?我们会像下面这样来一步一步计算:

1+2=3
3+3=6
6+4=10
........

结果

这个“熊孩子”只用了 20 分钟就给出了答案,因为他想到了用(1+100)+(2+99)+(3+98)……+(50+51)……一共有50101,所以50×101就是 1+2+3+...100 的总和。

这个“熊孩子”名叫 高斯 ,后来著名的犹太数学家 约翰·卡尔·弗里德里希·高斯,后来人们把这种简便算法称作 高斯算法

这是数学领域中算法的一个简单示例。

# 1、到底什么是算法 ?

TIP

  • 在数学领域中,算法是用来解决某一类问题的公式和思想。
  • 而在计算机科学领域中,它本质是一系列程序指令,用来解决特定的运算逻辑问题
  • 在计算机中,算法就是把一个问题,拆解为计算机能够一步一步执行的步骤

衡量算法的好坏:

算法有简单的也有复杂的,衡量算法的好环有以下几个指标

  • 时间复杂度:代码运行得到结果所花的时间
  • 空间复杂度: 代码运行是所占用的内存空间大小
  • 正确性(经得起时间、规模、大范围应用也不会出错)
  • 健壮性:是指一个计算机系统在执行过程中处理错误,以及算法在遭遇输入、运算等异常时继续正常运行的能力
  • 可读性

计算机的优势

  • 计算机最突出的能力就是计算,它没有归纳总结、逻辑推理的能力。
  • 所以人们使用计算机解决问题的时候,要"扬长避短"
  • 充分发挥计算机的计算优势,而不要让它进行逻辑推理

但并不意味着,我们就可以完全不考虑计算机在计算一个算法时所需要耗费的时间和占用的内存。相同的结果,肯定是耗时越小,占用的内存空间越小越好了。

所以我们在写算法时,需要考虑算法的复杂度,那什么是算法的复杂度呢 ?我们暂时不学习,我们先做几道算法题,找找感觉,然后再下下节课,我们来重点学习算法的复杂度。

# 2、累加器

由用户输入数字 n,请计算下面算式的值

+ + + ...... +

首先我们来找规律:

  • 第一项是分母是从 2 开始的,每一项分子比分母大 1
  • 所以在 for 循环,遍历时,只需要遍历分母就好,分母为 i ,分子为 i+1
// 由用户输入数字n,计算 3/2 + 4/3 + 5/4 + ... + (n+1)/n 的结果

// 用户输入数字n
var n = Number(prompt("请输入数字n"));

// 累加器
var sum = 0;
// 遍历分母就可以了,因为分子就是分母加1有关系
for (var i = 2; i <= n; i++) {
  sum += (i + 1) / i; // 每一项值 i+1/i
}
// 输出累加结果
alert(sum.toFixed(2)); // 这里要特别注意小数的处理

# 3、累乘器

TIP

由用户输入数字 n,请计算 n 的阶乘

5的阶乘 = 5 * 4 * 3 * 2 * 1
// 计算阶乘

// 用户输入数字n
var n = Number(prompt("请输入数字"));

// 累成器,一定要注意,累成器要从1开始,因为如果从0开始,0乘以任何数子都是0
var result = 1;

// 倒着遍历,计算阶乘
for (var i = n; i >= 1; i--) {
  result *= i;
}

// 显示结果
alert(result);

# 4、累加器与累乘器的结合

大厂经典面试真题

圆周率 π 可以由下面的莱布尼茨级数公式计算出来,请由用户输入参数 n,计算圆周率 π

π

  • 通过上面公式,得到圆周率 π = 2 * (1 + 1/3 + (1*2)/(3*5) + (1*2*3)/(3*5*7) + (1*2*3*4)/(3*5*7*9)) + (1*2* ... *n)/(3*5*...*(2n+1));
  • 第一步:找规律 ,除去第 1 项,每一项都等于前一项 * n/(n*2+1)
  • 这里需要用到累乘器来计算出每一项的值
  • 然后利用累加器,把每一项加起来
// 累加器,就是最后的答案
var sum = 0;
// 累乘器,用来制作每一项,制作出来的这个项,要往累加器中累加
var item = 1;

// 让用户输入n
var n = Number(prompt("请输入数字n"));

// 遍历
for (var i = 1; i <= n; i++) {
  // 要先制作项目
  item *= i / (2 * i + 1);
  console.log(item);
  // 把每一项往累加器中累加
  sum += item;
}

// 显示结果
alert((1 + sum) * 2);

注意:

算法题最难的点在于找到背后的规律,和相关的一些通用处理算法的技巧。

# 5、穷举法

穷举法是什么 ?

穷举法的基本思想是根据题目的部分条件确定答案的大致范围,并在此范围内对所有的情况逐一验证,直到全部情况验证完毕。

  • 若某个情况验证符合题目的全部条件,则为本问题的一个解
  • 若全部情况验证后都不符合题目的全部条件,则本题无解。
  • 穷举法也称为枚举法

穷举法是一种算法思想,把在条件范围内的所有情况都逐一验证一遍。

# 6、穷举法应用:寻找能被整除的数

算法题目:

寻找 100 以内的既能被 3 整除,也能被 5 整除的数字

  • 如果让人类来计算,人类会找规律或公式,如下

image-20211219195336969

  • 如果计算机来做:如下

计算机不会找规律 和逻辑推理,他最大的优势就是强大的计算能力

image-20211219200006028

// 寻找100以内的既能被3整除,也能被5整除的数字
// 穷举法,从1开始实验
for (var i = 1; i <= 100; i++) {
  if (i % 3 == 0 && i % 5 == 0) {
    console.log(i); // 15、30、45、60、75、90
  }
}

# 7、穷举法应用:寻找约数

算法题目:

用户输入一个数字,在控制台显示这个数字的全部约数

// 什么是约数:举例如下

48的约数 : 12346812162448

// 这些数字都是能够整除48的
// 或者说 让48除以这些数字,余数都是0
// 寻找约数

// 用户输入数字 n
var n = Number(prompt("请输入数字"));

// 穷举法 从1开始验证
for (var i = 1; i <= n; i++) {
  if (n % i == 0) {
    console.log(i);
  }
}

# 8、穷举法应用:寻找符合条件的数字

算法题目:

请问 1~100 中哪个数字除以 3 余 1,除以 4 余 2,除以 5 余 3 ?

// 寻找1~100的符合条件的数字:除以3余1,除以4余2,除以5余3
// 使用穷举法
for (var i = 1; i <= 100; i++) {
  if (i % 3 == 1 && i % 4 == 2 && i % 5 == 3) {
    console.log(i); // 58
  }
}

image-20211218170650143

# 9、穷举法应用:求水仙花数

算法题目:

请输入一个三位数,判断这个数是不是水仙花数

什么是水仙花数 ?

  • 如果一个数是水仙花数,那么这个数的个位 3 次方+十位数的 3 次方+百位数的 3 次方=这个数本身
  • 如 153 ,其中 13 + 53 + 33=153 ,这里的 153 就是水仙花数
  • 如 154,其中 13 + 53 + 43 = 190,所以这里的 154 不是水仙花数

代码实现思路:

利用穷举法,把 100 到 999 之内的所有数字都验证一遍。(要求是一个三位数)

将一个 3 位数,拆成个位、十位、百位

image-20211217203754752

实现方式有两种方法:

数学方法

  • 百位/100 取整
  • 十位/10 取整
  • 个位%10 求模

字符串方法

  • 利用 charAt()方法找到是应的个,十,百位
  • charAt()方法返回指定索引位置的 char 值
  • str.charAt(index); str 要检索的字符串,index 查找的索引,字符串中第一个字符下标是 0,index 为正整数
<script>
  var n = Number(prompt("请输入一个3位数的整数"));
  if (!isNaN(n) && n >= 100 && n <= 999 && n.length == 3) {
    var a = parseInt(n / 100);
    var b = parseInt(n / 10) % 10;
    var c = n % 10;
    if (a * a * a + b * b * b + c * c * c == n) {
      alert(n + "是水仙花数");
    } else {
      alert(n + "不是水仙花数");
    }
  } else {
    alert("你输入的数字不合法!");
  }
</script>
<script>
  var n = prompt("请输入一个3位数的整数");
  if (!isNaN(n) && n >= 100 && n <= 999 && n.length == 3) {
    var a = n.charAt(0);
    var b = n.charAt(1);
    var c = n.charAt(2);

    if (a * a * a + b * b * b + c * c * c == n) {
      alert(n + "是水仙花数");
    } else {
      alert(n + "不是水仙花数");
    }
  } else {
    alert("你输入的数字不合法!");
  }
</script>

# 10、穷举法应用:寻找质数

算法题目:

请寻找 1 ~ 100 的所有质数

  • 质数:只能被 1 和它本身整除的数字,最小的质数是 2
  • 比如:2、3、5、7、11、13、17、19、23、29 ......
// 寻找100以内的质数

// 穷举法
outer: for (var i = 2; i <= 100; i++) {
  // 内层循环开始从2开始到小于这个数字的每一个数字都尝试除i,如果能够整除,说明它不是质数,就可以筛选下一个数字了
  for (var j = 2; j < i; j++) {
    if (i % j == 0) {
      // 说明数字 i不是质数,因为它找到了除1和它自身之外的约数了
      // continue表示放弃这个数字,开始迭代下个数字,continue它负责的是它所在的最内层的for循环
      // 要给for循环加上label,然后在continue的后面加上这个label
      // 这样就表示立即开始迭代外层for循环的下一个数字了,而不是内层for循环
      continue outer;
    }
  }

  // 能够遇见这条语句的数字i,一定是质数,否则就被continue略过了
  console.log(i);
}

# 11、穷举法应用:鸡兔同笼

中国古代的数学著作《孙子算经》中记载了这样的一道题:

“今有雉兔同笼,上有三十五头,下有九十四足,问雉兔各几何 ?”

这四句的意思就是:

有一些鸡和兔子在同一个笼子里,从上面看有 35 个头;从下面看有 94 条腿.请求出笼中的鸡和兔子各有几只?

image-20211219233402701

数学方法解题思路:

  • 鸡和兔子各有一个头:a + b = 35
  • 鸡有 2 只脚,兔子有 4 只脚:2a + 4b = 94
image-20211219234905428

计算所得: a = 23 ;b = 12;

// 鸡兔同笼

// 方法1:
// 假设小鸡有a只,兔子有b只
for (var a = 0; a <= 35; a++) {
  for (var b = 0; b <= 35; b++) {
    if (a + b == 35 && 2 * a + 4 * b == 94) {
      console.log("小鸡有:" + a + "只,兔子有:" + b + "只。"); // 小鸡有:23只,兔子有:12只。
    }
  }
}

// 方法2:优化算法(减少for循环的次数)
for (var a = 0; a <= 35; a++) {
  var b = 35 - a;
  if (2 * a + 4 * b == 94) {
    console.log("小鸡有:" + a + "只,兔子有:" + b + "只。"); // 小鸡有:23只,兔子有:12只。
  }
}

# 12、算法如何学习 ?

TIP

在早期,我们学算法,学数据结构,最重要的是学基本功,只有把基本功学好了,算法的基本功就是算法的复杂度和数据结构。然后

上次更新时间: 6/8/2023, 9:23:17 PM

大厂最新技术学习分享群

大厂最新技术学习分享群

微信扫一扫进群,获取资料

X