vue3源码中的最长递增子序列

求解最长递增子序列是一道经典的算法题,

多数解法是使用动态规划的思想,算法的时间复杂度是O(n^2);

 而Vue.js内部使用的是维基百科提供的一套“贪心+二分查找”的算法;

贪心算法的时间复杂度是O(n),二分查找的时间复杂度是O(logn),总时间复杂度是O(nlogn)

主要思路:

对数组遍历,依次求解长度为i时的最长递增子序列

当i元素大于i-1的元素时,添加i元素并更新最长子序列

否则往前查找直到找到一个比i小的元素,然后插在该元素后面并更新对应的最长递增子序列

主要目的:

让递增序列的差尽可能的小,从而可以获得更长的递增子序列,是一种贪心算法的思想

源码

<!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>
    <script>
      function getSequence(arr) {
        const p = arr.slice();
        const result = [0]; // 存储长度为I的递增子序列的索引
        let i, j, u, v, c;
        const len = arr.length;
        debugger;
        for (i = 0; i < len; i++) {
          const arrI = arr[i];
          if (arrI !== 0) {
            j = result[result.length - 1];
            // result存的最后一个值小于当前值
            if (arr[j] < arrI) {
              // 存储在result更新前的最后一个索引的值
              p[i] = j;
              result.push(i);
              continue;
            }
            u = 0;
            v = result.length - 1;
            // 二分搜索,查找比arrI小的节点,更新result的值
            while (u < v) {
              c = (u + v) >> 1;
              if (arr[result[c]] < arrI) {
                u = c + 1;
              } else {
                v = c;
              }
            }
            if (arrI < arr[result[u]]) {
              if (u > 0) {
                p[i] = result[u - 1];
              }
              result[u] = i;
            }
          }
        }
        u = result.length;
        v = result[u - 1];
        // 回溯数组p,找到最终的索引
        while (u-- > 0) {
          result[u] = v;
          v = p[v];
        }
        return result;
      }

      const arr = [2, 1, 5, 3, 6, 4, 8, 9, 7];
      const resultIndex = getSequence(arr);
      console.log("最长递增子序列的索引是:", resultIndex);
      let result = [];
      resultIndex.forEach((item, index) => {
        result.push(arr[item]);
      });
      console.log("最长递增子序列:", result);
    </script>
  </body>
</html>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yusirxiaer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值