JavaScript 必看!算法 O 系列全攻略

一、O(1):常数时间复杂度

想象你去便利店买一瓶水,不管店里有多少瓶水,拿一瓶结账的时间是不是基本固定?这就是 O(1) 的典型场景。算法执行时间和输入数据规模无关,不管数据有多大,执行时间都基本不变。

就像取数组最后一个元素:

ini 复制代码
function getLastElement(arr) {
    return arr[arr.length - 1];
}

let arr = [1, 2, 3, 4, 5];
console.log(getLastElement(arr)); // 输出:5

不管数组多长,取最后一个元素的时间是固定的,这就是 O(1)。

二、O(n):线性时间复杂度

假设你去麦当劳排队买汉堡,队伍里每人买一个汉堡,收银员依次为每个人服务。队伍越长(n 越大),收银员服务完所有人的时间就越长,而且大致成正比关系,这就是 O(n)。

比如遍历数组打印每个元素:

ini 复制代码
function printElements(arr) {
    for (let i = 0; i < arr.length; i++) {
        console.log(arr[i]);
    }
}

let arr = [1, 2, 3, 4, 5];
printElements(arr);

数组有 n 个元素,循环就转 n 圈,打印 n 次。执行时间随着数组长度 n 线性增长,这就是 O(n)。

三、O(n²):二次时间复杂度

想象一个聚会,每个人都要和其他每个人握手一次。假设有 n 个人,总共握手次数大致是 n² 次。随着人数增加,握手次数呈平方级增长,算法执行时间也是如此。

比如打印数组元素的所有组合:

ini 复制代码
function printPairs(arr) {
    for (let i = 0; i < arr.length; i++) {
        for (let j = 0; j < arr.length; j++) {
            console.log(arr[i] + ", " + arr[j]);
        }
    }
}

let arr = [1, 2, 3];
printPairs(arr);

外层循环执行 n 次,内层循环每次也执行 n 次,总操作次数是 n*n 次,这就是 O(n²)。

四、O(log n):对数时间复杂度

想象你有一本字典,想查一个字,你会直接打开中间那一页,看字在前半部分还是后半部分,继续在对应的那一半里找,直到找到为止。这个过程的操作次数大致和 log₂n 成正比。

二分查找法就是典型例子:

ini 复制代码
function binarySearch(arr, target) {
    let left = 0;
    let right = arr.length - 1;
    while (left <= right) {
        let mid = Math.floor((left + right) / 2);
        if (arr[mid] === target) {
            return mid;
        } else if (arr[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return -1;
}

let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(binarySearch(arr, 5)); // 输出:4
console.log(binarySearch(arr, 10)); // 输出:-1

每次循环将查找范围缩小一半,对于长度为 n 的数组,最多需要 log₂n 次循环,这就是 O(log n)。

五、常见时间复杂度对比

  • O(1) :最优,执行时间固定。
  • O(log n) :次优,执行时间增长缓慢。
  • O(n) :执行时间线性增长。
  • O(n²) :较差,执行时间呈平方级增长。

宝子们,现在对算法时间复杂度是不是有了更全面的认识?以后写 JavaScript 代码要多想想这些知识,尽量写出高效代码。这一期的内容就到这里咯,下期再见!

相关推荐
在下历飞雨几秒前
Kuikly基础之动画实战:让孤寡青蛙“活”过来
前端·ios·harmonyos
2***c4355 分钟前
nginx服务器实现上传文件功能_使用nginx-upload-module模块
服务器·前端·nginx
p***93038 分钟前
Java进阶之泛型
android·前端·后端
木易 士心11 分钟前
Element UI 多级菜单缩进的动态控制:从原理到工程化实践
前端·vue.js·ui
狮子座的男孩15 分钟前
js函数高级:03、详解原型与原型链(原型、显式原型与隐式原型、原型链、原型链属性、探索instanceof、案例图解)及相关面试题
前端·javascript·经验分享·显示原型与隐式原型·原型链及属性·探索instanceof·原型与原型链图解
烛阴16 分钟前
C#继承与多态全解析,让你的对象“活”起来
前端·c#
狗哥哥19 分钟前
Swagger对接MCP服务:赋能AI编码的高效落地指南
前端·后端
zl_vslam20 分钟前
SLAM中的非线性优-3D图优化之相对位姿Between Factor(六)
前端·人工智能·算法·计算机视觉·slam se2 非线性优化
申阳20 分钟前
Day 18:01. 基于 SpringBoot4 开发后台管理系统-快速了解一下 SpringBoot4 新特性
前端·后端·程序员
500佰24 分钟前
技术包办模式给我带来的反思
前端