Day 1:为什么要学算法?

4 阅读14分钟

今天是第一天!让我们轻松入门~
不写复杂代码,先理解算法是什么!
预计时间:1.5-2 小时(含费曼输出)


📖 第 1 步:明确今天的学习目标(5 分钟)

✅ 学完这一章,你将明白:

□ 算法到底是什么?(用做菜比喻)
□ 算法在我们身边有哪些应用?
□ 什么是时间复杂度?(不是真的计时!)
□ 大 O 表示法是什么意思?
□ 如何比较两个算法谁更快?

🎯 今天的任务清单

□ 看故事理解算法概念(20 分钟)
□ 学习生活中的算法例子(20 分钟)
□ 理解时间复杂度(30 分钟)
□ 完成费曼输出 #1(20 分钟)
□ 做练习题(20 分钟)
□ 录视频或写文章总结(20 分钟)

准备好了吗?开始吧! 🚀


🍳 第 2 步:算法到底是什么?(20 分钟)

故事时间:你要做一道"西红柿炒鸡蛋"

❌ 方法一:瞎做一气

// 没有算法的后果...

function makeDarkCuisine() {
    把鸡蛋打进锅里;      // 壳也进去了 😱
    放西红柿;           // 没洗 🤢
    倒油;              // 油还没热 🔥
    加盐;              // 手抖倒了半袋 🧂
    出锅;              // 已经糊了 ⚫
}

// 结果:黑暗料理,根本没法吃!
makeDarkCuisine(); // 💩

问题出在哪里? → 没有步骤!想到哪做到哪!


✅ 方法二:按照菜谱做

// 这就是算法!

function makeTomatoScrambledEggs() {
    // 第 1 步:准备食材
    washTomato();           // 洗净西红柿
    cutTomato();            // 切成块
    beatEggs();             // 打鸡蛋,加少许盐
    
    // 第 2 步:炒鸡蛋
    heatPan();              // 锅烧热
    addOil();               // 倒油
    fryEggs();              // 炒熟盛出
    
    // 第 3 步:炒西红柿
    stirFryTomato();        // 翻炒西红柿
    
    // 第 4 步:混合
    mixEggsAndTomato();     // 加入鸡蛋
    
    // 第 5 步:调味
    addSalt();              // 加盐
    addSugar();             // 加糖(提鲜)
    
    // 第 6 步:出锅
    serve();                // 装盘
}

// 结果:色香味俱全!
makeTomatoScrambledEggs(); // 🍽️😋

这就是算法!


💡 算法的定义

官方说法:

算法是解决问题的一系列明确指令

人话版:

算法 = 解决问题的步骤清单

就像做菜一样:

输入:鸡蛋、西红柿、油、盐
       ↓
处理步骤:洗、切、炒、调味(按顺序来)
       ↓
输出:一盘香喷喷的西红柿炒鸡蛋

🎯 好算法的特点

1️⃣ 有穷性 - 步骤有限

✅ 好算法:
function goodAlgorithm() {
    step1();
    step2();
    step3();
    // 结束了!
}

❌ 坏算法:
function badAlgorithm() {
    while(true) {
        doSomething();
        // 无限循环,永远停不下来!
    }
}

生活例子:

  • ✅ 菜谱:8 个步骤,做完就结束
  • ❌ "一直炒直到地球毁灭" → 这菜谁敢吃?

2️⃣ 确定性 - 每一步都清清楚楚

✅ 好算法:
function goodRecipe() {
    addSalt(3);          // 加 3 克盐
    cookFor(30);         // 炒 30 秒
    cutInto(8);          // 切成 8 块
}

❌ 坏算法:
function badRecipe() {
    addSalt('适量');      // 多少是适量?🤔
    cookFor('一会儿');    // 多久是一会儿?⏰
    cutInto('小块');      // 多小算小块?🤏
}

计算机很笨的,必须告诉它精确的指令!


3️⃣ 可行性 - 每一步都能做到

✅ 好算法:
function feasible() {
    boilWater();         // 烧水 - 能做到
    cutVegetables();     // 切菜 - 能做到
    stirFry();           // 炒菜 - 能做到
}

❌ 坏算法:
function impossible() {
    flyToSun();          // 飞到太阳上 - 做不到啊!☀️
    catchStar();         // 摘星星 - 太难了吧!⭐
    makeTimeMachine();   // 造时光机 - 科幻片看多了!⏰
}

4️⃣ 有输入和输出

// 可以没有输入,也可以有多个输入
function noInput() {
    return getRandomNumber();  // 不需要输入
}

function multiInput(a, b, c) {
    return a + b + c;  // 三个输入
}

// 至少有一个输出
function withOutput(data) {
    const result = processData(data);
    return result;  // 必须有返回值
}

生活例子:

输入:食材
       ↓
算法:做菜的步骤
       ↓
输出:做好的菜 + 吃饱了的满足感 😋

🌍 第 3 步:算法在我们身边(20 分钟)

📱 例子 1:抖音为什么总给你推爱看的视频?

问题场景

抖音上有几亿个视频
怎么知道你想看什么?

❌ 传统方法:随机推荐

function randomRecommend() {
    const videos = getAllVideos();  // 几亿个视频
    const randomVideo = videos[Math.floor(Math.random() * videos.length)];
    return randomVideo;
}

// 结果:
你:划走、划走、划走... 😑
"这都是些什么鬼东西!"
最后:卸载抖音 😤

✅ 机器学习算法:智能推荐

// 抖音的推荐算法工作流程

const recommendationSystem = {
    // 第 1 步:记录你的行为
    trackBehavior: function() {
        return {
            watched: ['做菜视频', '猫咪视频', '编程教程'],
            liked: ['3 分钟快手菜', '橘猫日常'],
            commented: ['这个好用!'],
            shared: ['已转发给闺蜜'],
            watchTime: {
                '做菜视频': '平均看完 90%',
                '游戏视频': '平均看 3 秒就划走'
            }
        };
    },
    
    // 第 2 步:给你贴标签
    createProfile: function() {
        return {
            tags: ['美食爱好者', '猫奴', '学习型用户'],
            preferences: {
                '美食': 0.9,    // 超级喜欢
                '宠物': 0.8,    // 很喜欢
                '游戏': 0.1,    // 无感
                '八卦': 0.0     // 完全不看
            }
        };
    },
    
    // 第 3 步:找相似用户
    findSimilarUsers: function() {
        return [
            '用户 A:和你一样喜欢做菜和猫',
            '用户 B:也是学习型用户',
            '用户 C:口味跟你很像'
        ];
    },
    
    // 第 4 步:推荐给你
    recommend: function() {
        // 看看相似用户都在看什么
        const similarUsersVideos = this.findSimilarUsers();
        const recommendations = [];
        
        for (let user of similarUsersVideos) {
            if (user.likes['美食'] && user.likes['宠物']) {
                recommendations.push('新出的做菜视频');
                recommendations.push('可爱的猫咪视频');
            }
        }
        
        return recommendations;
    }
};

// 结果:
你:越刷越爱看,根本停不下来!📱⏰
"抖音太懂我了!"

这就是机器学习算法的威力!


🗺️ 例子 2:导航软件怎么找到最快路线?

问题场景

从家到公司有 100 条路可以走
哪条最快?

❌ 笨办法:一条一条试

function stupidFindRoute() {
    const routes = getAllRoutes();  // 100 条路
    
    for (let i = 0; i < routes.length; i++) {
        console.log(`第${i+1}天:尝试 route ${i}`);
        
        if (routes[i] === '畅通') {
            return routes[i];
        }
        // 每条路都要开一次才知道...
    }
    
    // 等你找到最快的路,已经过了 100 天!😫
}

✅ Dijkstra 算法:智能规划

// 高德地图的导航算法

class NavigationSystem {
    constructor() {
        this.roads = new Map();  // 存储所有道路信息
    }
    
    // 收集实时数据
    collectTrafficData() {
        return {
            roadLength: '每条路的长度',
            trafficJam: '实时车流量',
            trafficLights: '红绿灯数量',
            speedLimit: '限速情况',
            accident: '前方事故'
        };
    }
    
    // 计算所有可能的路线
    dijkstra(start, end) {
        // 用图论算法快速计算
        // 0.1 秒内算出 1000 条路线
        
        const distances = {};      // 到每个路口的时间
        const previous = {};       // 记录路径
        const unvisited = new Set(); // 未访问的路口
        
        // ... 复杂的算法逻辑
        
        return shortestPath;  // 返回最短路径
    }
    
    // 选出最优的
    findBestRoute() {
        const routes = this.dijkstra('家', '公司');
        
        return routes.sort((a, b) => {
            // 按时间排序
            return a.time - b.time;
        })[0];  // 返回时间最短的
    }
    
    // 实时调整
    adjustRoute() {
        // 前方事故?马上换路线!
        // 新修了路?重新计算!
    }
}

// 使用
const nav = new NavigationSystem();
const bestRoute = nav.findBestRoute();

console.log(bestRoute);
// 输出:"走这条路,预计 35 分钟到达" 🚗

这就是图论算法的应用!


🛒 例子 3:淘宝"猜你喜欢"怎么那么准?

现象

你刚看过一双鞋
淘宝立马推荐相似的

背后的协同过滤算法

// 淘宝的推荐系统

class TaobaoRecommender {
    constructor(userId) {
        this.userId = userId;
        this.history = this.getUserHistory();
    }
    
    // 第 1 步:分析你的浏览记录
    getUserHistory() {
        return {
            viewed: [
                { item: 'Nike 运动鞋', count: 3 },
                { item: 'Adidas 外套', count: 2 },
                { item: '运动水壶', count: 1 }
            ],
            purchased: [
                '运动袜',
                '健身包'
            ]
        };
    }
    
    // 第 2 步:给你贴标签
    createUserTags() {
        return {
            '运动爱好者': 0.9,
            '品牌控': 0.7,
            '价格敏感': 0.8  // 只看打折的
        };
    }
    
    // 第 3 步:找相似商品
    findSimilarItems() {
        // 其他买 Nike 的人也买了什么?
        const coPurchased = [
            '运动袜',
            '护腕',
            '运动背包'
        ];
        
        // 运动爱好者通常需要什么?
        const categoryMatch = [
            '跑步机',
            '哑铃',
            '瑜伽垫'
        ];
        
        return [...coPurchased, ...categoryMatch];
    }
    
    // 第 4 步:推荐给你
    recommend() {
        const items = this.findSimilarItems();
        
        return items.map(item => ({
            name: item,
            reason: '根据你的浏览记录推荐',
            discount: '限时 8 折'  // 诱惑你下单 😏
        }));
    }
}

// 使用
const recommender = new TaobaoRecommender('小明');
const recommendations = recommender.recommend();

console.log(recommendations);
// 输出:一堆你忍不住想买的东西!💸

结果:你又剁手了!


⏱️ 第 4 步:时间复杂度详解(30 分钟)

❓ 先问个问题

场景:在一个班级里找到身高最高的同学

方法一:一个一个比

function findTallest(students) {
    let tallest = students[0];  // 假设第一个最高
    
    // 从第二个开始比较
    for (let i = 1; i < students.length; i++) {
        if (students[i] > tallest) {
            tallest = students[i];  // 发现更高的,更新
        }
    }
    
    return tallest;
}

问题:这个函数要执行多少次比较?

答案:

10 个学生 → 比较 9 次
100 个学生 → 比较 99 次
n 个学生 → 比较 n-1 次

结论:学生越多,比较次数越多,成正比关系

方法二:先排序再取最后一个

function findTallest2(students) {
    // 先排序(冒泡排序)
    for (let i = 0; i < students.length; i++) {
        for (let j = 0; j < students.length - i - 1; j++) {
            if (students[j] > students[j + 1]) {
                // 交换
                let temp = students[j];
                students[j] = students[j + 1];
                students[j + 1] = temp;
            }
        }
    }
    
    // 返回最后一个(最大的)
    return students[students.length - 1];
}

问题:这个函数要执行多少次比较?

答案:

10 个学生  比较约 45 次(10×9÷2)
100 个学生  比较约 4950 次(100×99÷2)
n 个学生  比较约 n²/2 

结论:学生越多,比较次数爆炸式增长!💥

💡 什么是时间复杂度?

重要概念:

时间复杂度 ≠ 实际运行时间

不是说"这个方法跑 1 秒,那个方法跑 2 秒"

而是:随着输入规模增大,操作次数增长得有多快

赛车比喻:

不是比谁跑得快(绝对时间)
而是比速度增加的趋势(加速度)

数据规模变大时:
- 有的算法依然很快(O(1))
- 有的算法变慢一点(O(n))
- 有的算法直接崩盘(O(n²))

🎯 三种常见的时间复杂度

1️⃣ O(1) - 常数时间(最快!)

特点: 不管多少数据,都只执行一次

// 例子:数组取第一个元素
function getFirst(arr) {
    return arr[0];  // 就这一步,永远不变!
}

// 测试
getFirst([1, 2, 3]);              // 1 步
getFirst([1, 2, 3, ..., 1000]);   // 还是 1 步!
getFirst([1, 2, 3, ..., 1000000]);// 依然是 1 步!不可思议!

生活比喻:

✓ 电影院找第一排的座位 → 直接走过去就行
✓ 吃火锅夹第一片肉 → 筷子伸进去就夹到
✓ 打开冰箱拿第一瓶可乐 → 伸手就拿

图像:

操作次数
   |
 1 |—————— 一条直线,永远不变
   |
   +——————→ 数据量 n

2️⃣ O(n) - 线性时间(还不错)

特点: 数据量翻倍,操作次数也翻倍

// 例子:遍历数组找最大值
function findMax(arr) {
    let max = arr[0];
    
    for (let i = 1; i < arr.length; i++) {
        if (arr[i] > max) {
            max = arr[i];
        }
    }
    
    return max;
}

// 测试
findMax([1, 2, 3]);              // 循环 2 次
findMax([1, 2, 3, ..., 100]);    // 循环 99 次
findMax([1, 2, 3, ..., 1000]);   // 循环 999 次!

生活比喻:

✓ 点名册找人 → 一个一个念名字
✓ 超市排队结账 → 前面有几个人就要等多久
✓ 老师批改试卷 → 一份一份改

图像:

操作次数
   |         /
   |       /
   |     /  斜线上升,成正比
   |   /
   | /
   +——————→ 数据量 n

3️⃣ O(n²) - 平方时间(太慢了!)

特点: 数据量翻倍,操作次数翻 4 倍(爆炸!)

// 例子:冒泡排序
function bubbleSort(arr) {
    for (let i = 0; i < arr.length; i++) {
        for (let j = 0; j < arr.length - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                // 交换
                let temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

// 测试
bubbleSort([1, 2, 3]);              // 约 9 次操作
bubbleSort([1, 2, 3, ..., 100]);    // 约 4950 次操作
bubbleSort([1, 2, 3, ..., 1000]);   // 约 50 万次操作!!!

生活比喻:

✓ 全班同学两两握手 → 每个人都跟其他人握一次
✓ 聚餐时所有人互相敬酒 → 一个人敬一圈
✓ 比赛中的循环赛 → 每个队都要跟其他队打一场

图像:

操作次数
   |        _
   |      /
   |    /   曲线暴涨,受不了!
   |  /
   |/
   +——————→ 数据量 n

📊 直观对比表

数据量 nO(1)O(n)O(n²)
101 次10 次100 次
1001 次100 次10,000 次
10001 次1000 次1,000,000 次
100001 次10000 次100,000,000 次

看到了吗?

O(1):稳如老狗,永远 1O(n):老老实实,多少数据干多少次
O(n²):指数爆炸,数据多了直接崩盘!💥

🎯 费曼输出 #1:解释算法和复杂度(20 分钟)

任务 1:向小学生解释算法

要求:

  • 不用"指令"、"流程"这些术语
  • 用生活中的例子比喻
  • 让小学生能听懂

参考模板:

"算法就像______一样。

比如你要______,
没有算法会______,
有算法就会______。

区别就是______。"

⏰ 时间:10 分钟


任务 2:解释时间复杂度

场景:

小朋友问:"为什么有些程序快,有些程序慢?"

你要解释:

  1. O(1) 是什么意思?(用寻宝游戏比喻)
  2. O(n) 是什么意思?(用点名比喻)
  3. O(n²) 是什么意思?(用握手游戏比喻)

要求:

  • 至少创造 3 个不同的比喻
  • 用学校、游戏、运动等生活场景
  • 让小朋友能听懂

⏰ 时间:15 分钟


💡 卡壳检查点

如果你在解释时卡住了:

□ 我说不清楚算法和程序的区别
□ 我不知道如何用简单例子说明时间复杂度
□ 我只能背诵定义,不能用自己的话
□ 我解释不清为什么 O(n²) 比 O(n) 慢那么多

这很正常! 标记下来,回去再看上面的内容,然后重新尝试解释!


📝 第 5 步:课后练习(20 分钟)

基础题(必做)⭐

1. 用自己的话解释什么是算法(100 字以内)

提示: 不要用教科书上的定义,用自己的话说!


2. 列举 3 个你生活中用到的算法

示例:

□ 微信红包怎么分配金额?
□ 抖音怎么知道你喜欢看什么?
□ 导航怎么找到最快的路?

你的答案:

1. _________________________________
2. _________________________________
3. _________________________________

3. 比较以下两种方法的时间复杂度

// 方法 1
function method1(arr) {
    return arr[0];
}

// 方法 2
function method2(arr) {
    for (let i = 0; i < arr.length; i++) {
        console.log(arr[i]);
    }
}

// 方法 3
function method3(arr) {
    for (let i = 0; i < arr.length; i++) {
        for (let j = 0; j < arr.length; j++) {
            console.log(arr[i], arr[j]);
        }
    }
}

问题:

□ 方法 1 的时间复杂度是?O(?)
□ 方法 2 的时间复杂度是?O(?)
□ 方法 3 的时间复杂度是?O(?)
□ 哪个最快?哪个最慢?

进阶题(选做)⭐⭐

4. 写一个"泡方便面"的算法

要求:

/**
 * 输入:方便面、热水、碗
 * 步骤:???
 * 输出:一碗热腾腾的方便面
 */

function makeInstantNoodles() {
    // 你的代码
}

5. 调查一下:你常用的 App 用了哪些算法?

示例表格:

App 名称可能的算法作用
抖音推荐算法推荐你爱看的视频
美团路径规划规划外卖配送路线
支付宝风控算法防止被盗刷

你的调查:

| App 名称 | 可能的算法 | 作用 |
|---------|-----------|------|
| _______ | _________ | ____ |
| _______ | _________ | ____ |
| _______ | _________ | ____ |

挑战题(加分)⭐⭐⭐

6. 用 JavaScript 实现一个查找算法

// 在数组中查找数字 5

const arr = [1, 3, 5, 7, 9, 11, 13];

// 方法 1:顺序查找(笨办法)
function linearSearch(arr, target) {
    // 你的代码
}

// 方法 2:二分查找(聪明办法)- 提示:数组是有序的
function binarySearch(arr, target) {
    // 你的代码
}

// 比较两种方法的执行时间
console.time('linearSearch');
linearSearch(arr, 5);
console.timeEnd('linearSearch');

console.time('binarySearch');
binarySearch(arr, 5);
console.timeEnd('binarySearch');

// 思考:为什么二分查找更快?

🎁 彩蛋时间

程序员冷笑话

问:为什么程序员总是分不清万圣节和圣诞节?

答:因为 Oct 31 == Dec 25

(看不懂?等你学了进制转换就懂了!😂)

名言警句

"算法 + 数据结构 = 程序"
—— Niklaus Wirth(图灵奖得主)

"任何傻瓜都能写出计算机理解的代码。
优秀的程序员写出人类能理解的代码。"
—— Martin Fowler

📚 今日总结

✅ 你今天学到了:

1. 算法是什么

✓ 算法 = 解决问题的步骤清单
✓ 就像菜谱一样
✓ 有好算法和坏算法之分

2. 算法在哪里

✓ 抖音推荐、导航路线、淘宝购物
✓ 无处不在!
✓ 让我们的生活更便利

3. 时间复杂度

O(1) < O(n) < O(n²)
✓ 数据量大时差距明显
✓ 选择算法要考虑复杂度

📊 知识框架图

算法
├── 定义:解决问题的步骤
├── 特点:有穷、确定、可行、有输入输出
└── 应用:推荐系统、导航、电商

时间复杂度
├── O(1):最快,永远 1 步
├── O(n):中等,数据量=操作次数
└── O(n²):最慢,数据量平方增长

🎤 费曼输出展示区

录制你的讲解视频

任务: 假装你在给一个完全不懂的人上课

要覆盖:

  1. 算法是什么(用做菜比喻)
  2. 时间复杂度是什么(用赛跑比喻)
  3. O(1)、O(n)、O(n²) 的区别

方式:

  • 📹 录一段 5-8 分钟的视频
  • 📝 写一篇 500 字左右的文章
  • 👥 找个朋友,真的讲给他听

⏰ 时间:20 分钟


📞 打卡模板

╔═══════════════════════════════════════╗
║         Day 1 学习打卡                ║
╠═══════════════════════════════════════╣
║ 日期:__________                     ║
║ 学习时长:__________                 ║
╠═══════════════════════════════════════╣
║                                       ║
║ 今天我学会了:                       ║
║ □ 算法是什么                         ║
║ □ 时间复杂度概念                     ║
║ □ O(1)、O(n)、O(n²) 的区别           ║
║                                       ║
║ 我的通俗比喻:                       ║
║ • 算法就像 ______                    ║
║ • O(1) 就像 ______                  ║
║ • O(n) 就像 ______                  ║
║                                       ║
║ 我还想知道:                         ║
║ _________________________________    ║
║                                       ║
╚═══════════════════════════════════════╝

🚀 下一章预告

明天你将学习:

主题:数组 - 最基础的数据结构

内容:
✓ 数组是什么?(电影院座位表)
✓ 访问元素为什么快?(门牌号找人)
✓ 增删改查操作详解
✓ 遍历数组的 N 种方法
✓ 实战:学生成绩管理系统

需要准备:
✓ 复习今天的复杂度概念
✓ 安装 Node.js 环境
✓ 准备好代码编辑器

💪 最后的鼓励

╔═══════════════════════════════════════╗
║                                       ║
║   第一天完成了!你真棒!🎉           ║
║                                       ║
║   昨天你可能还不懂算法               ║
║   今天你已经能用自己的话解释了!     ║
║                                       ║
║   继续保持!明天学习更有趣的内容!   ║
║                                       ║
║   记住:                               ║
║   每天进步一点点                     ║
║   30 天就是质的飞跃!                 ║
║                                       ║
╚═══════════════════════════════════════╝

明天见!继续加油!


学习时长统计:

  • 📖 阅读 + 理解:60 分钟
  • 💭 思考 + 笔记:20 分钟
  • ✍️ 练习 + 费曼输出:40 分钟
  • ⏰ 总计:约 2 小时 ✅