天天看點

遞歸及常見例子

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <!-- 遞歸:就是函數自己調用自己本身 -->
  <!-- 遞歸的步驟:尋找遞推規律的關系;判斷遞推關系的臨界條件;将遞推關系的結構轉換為遞歸體;将臨界條件加入遞歸體中 -->
  <!-- 
    遞歸通俗地講就是函數自己調用自己,它具有以下三要素
      1、一個問題可以分解為更小的問題用同樣的方法解決,
        分解後的子問題求解方式一樣,不同的是資料規模變小
        其實就是找互相關系,這個關系就是遞歸體展現的
      2、存在遞歸終止條件
    -->
  <script>
    // 分析:計算 1 + 2 + … + 99 + 100 的和
    function sum(n) {
      if (n === 1) return 1
      return sum(n - 1) + n
    }
    console.log(sum(5))


    // 計算 n 的階乘
    function fn(n) {
      if (n === 1) return 1
      return n * fn(n - 1)
    }

    // 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, … 求第 n 項
    // 分析:第1項和第2項都為1;第3項為第2項+第1項的和;第4項為第3項+第2項的和,可以看出遞推關系:第n項為第n-1項+第n-2項的和,即遞歸體是febo(n - 1) + febo(n - 2);臨界條件是:第1項和第2項都為1
    function febo(n) {
      if ([1, 2].includes(n)) return 1
      return febo(n - 1) + febo(n - 2)
    }
    console.log(fn(5))

    // 拿到每一級的最後一個資料的name值
    let list = [
      {
        name: "所有物品",
        children: [
          {
            name: "水果",
            children: [{name: "蘋果", children: [{name: '青蘋果'}, {name: '紅蘋果'}]}]
          },
          {
            name: '主食',
            children: [
              {name: "米飯", children: [{name: '北方米飯'}, {name: '南方米飯'}]}
            ]
          }
        ]
      }
    ]
    const arr = []
    function getName (data) {
      for (let i = 0; i < data.length; i++) {
        // 如果沒有children的屬性,就push進行;如果有children屬性,就繼續遞歸
        if (data[i].children) {
          getName(data[i].children)
        } else {
          arr.push(data[i].name)
        }
      }
      return arr
    }
    console.log('data---result', getName(list))

    // 求一個數組前n項的和
    function sumList (n, list) {
      if (n === 1) {
        return list[0]
      } else {
        // 遞歸體的計算規則:例如-->前三項的和 = 第三項的值 + 前兩項的值
        // 結束條件:如果計算前一項的和,傳回值就是第一項
        return (list[n-1] + sumList(n-1, list))
      }
    }
    const list1 = [1, 5, 7, 6, 9, 1]
    console.log('sumlist--result', sumList(3, list1))

    // 小明入職第一年月薪是10k,漲幅每年是8%,那麼20年後他的月薪是多少
    function addSalary (n) {
      if (n === 1) {
        return 1
      } else {
        return addSalary(n-1) * 1.08
      }
    }
    console.log('addSalary', addSalary(3))
  </script>
</body>
</html>