今天是第一天!让我们轻松入门~
不写复杂代码,先理解算法是什么!
预计时间: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
📊 直观对比表
| 数据量 n | O(1) | O(n) | O(n²) |
|---|---|---|---|
| 10 | 1 次 | 10 次 | 100 次 |
| 100 | 1 次 | 100 次 | 10,000 次 |
| 1000 | 1 次 | 1000 次 | 1,000,000 次 |
| 10000 | 1 次 | 10000 次 | 100,000,000 次 |
看到了吗?
O(1):稳如老狗,永远 1 次
O(n):老老实实,多少数据干多少次
O(n²):指数爆炸,数据多了直接崩盘!💥
🎯 费曼输出 #1:解释算法和复杂度(20 分钟)
任务 1:向小学生解释算法
要求:
- 不用"指令"、"流程"这些术语
- 用生活中的例子比喻
- 让小学生能听懂
参考模板:
"算法就像______一样。
比如你要______,
没有算法会______,
有算法就会______。
区别就是______。"
⏰ 时间:10 分钟
任务 2:解释时间复杂度
场景:
小朋友问:"为什么有些程序快,有些程序慢?"
你要解释:
- O(1) 是什么意思?(用寻宝游戏比喻)
- O(n) 是什么意思?(用点名比喻)
- 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²):最慢,数据量平方增长
🎤 费曼输出展示区
录制你的讲解视频
任务: 假装你在给一个完全不懂的人上课
要覆盖:
- 算法是什么(用做菜比喻)
- 时间复杂度是什么(用赛跑比喻)
- 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 小时 ✅