❤️两万字《算法 + 数据结构》全套路线❤️(建议收藏)
Posted 英雄哪里出来
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了❤️两万字《算法 + 数据结构》全套路线❤️(建议收藏)相关的知识,希望对你有一定的参考价值。
前言
所谓活到老,学到老,虽然我感觉自己已经学了很多算法了,但是昨天熬夜整理完以后发现,自己还是个弟弟,实在忍不住了,打算把 算法学习路线 发出来,我把整个算法学习的阶段总结成了五个步骤,分别为:基础语法学习、语法配套练习、数据结构、算法入门、算法进阶。本文梳理了这五个大项的思维导图,在下文会有详细介绍。
希望各位能够找到自己的定位,通过自己的努力在算法这条路上越走越远。
刚开始切勿心浮气躁,千万不要给自己立 flag,说一定要把这么多东西都学会。就算你的精力旺盛,日夜操劳,时间也是有限的。所以,首先是明确我们要做什么,然后制定好一个合理的 目标 ,再一点一点将要学习的内容逐步付诸实践才是最重要的。
1、基础语法学习
- 算法是以编程语言为基础的,所以选择一门编程语言来学习是必须的。
- 因为作者本身是C/C++技术栈的,所以就拿C语言来举例子吧。如果是 Java、Python 技术栈,可以跳过 C语言相关的内容。这一小节,先给出学习路线图,然后我再来讲,每部分应该如何去学。
1)HelloWorld
- 无论是 Java、Python、C/C++,想要上手一门语言,第一步一定是 HelloWorld,先不要急着去配环境。如果环境配了几个小时,可能一开始的雄心壮志就被配环境的过程消磨殆尽,更加不要谈日后的丰功伟业了。
2)让自己产生兴趣
- 所以,我们需要让这件事情从一开始就变得 有趣,这样才能坚持下去。比如找一个相对较为有趣的教程,这里我会推荐这个:《光天化日学C语言》。听名字就比较搞笑,可能作者本身也不是什么正经人,哈哈哈!虽然不能作为一个严谨的教程去学,起码可以对搞笑的内容先产生兴趣。从而对于语言本身有学习下去的动力。
- 刚才提到的这个系列,可以先收藏起来。回头再去看,它讲述的是 对白式 的 C语言教学,从最简单的输出 HelloWorld 这个字符串开始讲起,逐渐让读者产生对C语言的兴趣。这个系列的作者是前 WorldFinal 退役选手,一直致力于 将困难的问题讲明白 。我看了他的大部分教程,基本都能一遍看懂。算了,不装了,摊牌了,因为我就是这个作者。
3)目录是精髓
- 然后,我们大致看下你选择的教程的前几个章节,那些标题是否有你认知以外的名词出现,比如以这个思维导图为例,前几个章节为:
1、第一个C语言程序
2、搭建本地环境
3、变量
4、标准输出
5、标准输入
6、进制转换入门
7、ASCII字符
8、常量
- 如果你觉得这些名词中有 3 / 4 以上是没有什么概念的。那么,可能需要补齐一些数学、计算机方面的基础知识。反之,我们就可以继续下一步了。
4)习惯思考并爱上它
- 只要对一件事情养成习惯以后,你就会发现,再难的事情,都只是一点一点积累的过程。重要的是,每天学习的过程一定要吃透,养成主动思考的好习惯。因为,越到后面肯定是越难的,如果前期不养成习惯,后面很可能心有余而力不足。
- 就像刷题,一旦不会做就去找解题报告,最后就养成了看解题报告才会做题的习惯。当然这也是一种习惯,只不过不是一种好习惯罢了。
5)实践是检验真理的唯一标准
- 光看教程肯定是不行的,写代码肯定还是要动手的,因为有些语法你看一遍,必定忘记。但是写了几遍,永世难忘。这或许就是写代码的魅力所在吧。
- 所以,记得多写代码实践哟 (^U^)ノ~YO
6)坚持其实并没有那么难
- 每天把教程上的内容,自己在键盘上敲一遍,坚持一天,两天,三天。你会发现,第四天就变成了习惯。所以坚持就是今天做了这件事情,明天继续做。
7)适当给予正反馈
- 然而,就算再有趣的教程,看多了都会乏味,这是人性决定的,你我都逃不了。能够让你坚持下去的只有你自己,这时候,适当给予自己一些正反馈就显得尤为重要。比如,可以用一张表格将自己的学习计划记录下来,然后每天都去分析一下自己的数据。
- 当然,你也可以和我一样,创建一个博客,然后每天更新博文,就算没有内容,也坚持日更,久而久之,你会发现,下笔如有神,键盘任我行!更新的内容,可以是自己的学习笔记,心路历程 等等。
- 看着每天的粉丝量呈指数级增长,这是全网对你的认可,应该没有什么会是比这个更好的正反馈了。
8)学习需要有仪式感
- 那么,至此,不知道屏幕前的你感想如何,反正正在打字的我已经激情澎湃了。已经全然忘记这一章是要讲C语言基础的了!
- 介于篇幅,我会把C语言基础的内容,放在这个专栏 《光天化日学C语言》 里面去讲,一天更新一篇,对啊,既然说了要坚持,要养成习惯,我当然也要做到啦~如果你学到了哪一章,可以在评论区评论 “打卡” ,也算是一种全网见证嘛!
- 我也很希望大家的学习速度能够超越我的更新速度。
2、语法配套练习
- 学习的过程中,做题当然也是免不了的,还是应征那句话:实践是检验真理的唯一标准。
- 而这里的题库,是我花了大量时间,搜罗了网上各大C语言教程里的例题,总结出来的思维导图,可以先大致看一眼:
- 从数学基础、输入输出、数据类型、循环、数组、指针、函数、位运算、结构体、排序 等几个方面,总结出的具有概括性的例题 100 道 《C语言入门100例》,目前还在更新中。
- 这里可以列举几个例子:
1、例题1:交换变量的值
一、题目描述
循环输入,每输入两个数 a a a 和 b b b,交换两者的值后输出 a a a 和 b b b。当没有任何输入时,结束程序。
二、解题思路
难度:🔴⚪⚪⚪⚪
- 这个题的核心是考察如何交换两个变量的值,不像 python,我们可以直接写出下面这样的代码就实现了变量的交换。
a, b = b, a
- 在C语言里,这个语法是错误的。
- 我们可以这么理解,你有两个杯子 a a a 和 b b b,两个杯子里都盛满了水,现在想把两个杯子里的水交换一下,那么第一个想到的方法是什么?
当然是再找来一个临时杯子:
1)先把 a a a 杯子的水倒进这个临时的杯子里;
2)再把 b b b 杯子的水倒进 a a a 杯子里;
3)最后把临时杯子里的水倒进 b b b 杯子;
- 这种就是临时变量法,那么当然,还有很多很多的方法,接下来就让我们来见识一下吧。
三、代码详解
1、正确解法1:引入临时变量
#include <stdio.h>
int main() {
int a, b, tmp;
while (scanf("%d %d", &a, &b) != EOF) {
tmp = a; // (1)
a = b; // (2)
b = tmp; // (3)
printf("%d %d\\n", a, b);
}
return 0;
}
-
(
1
)
(1)
(1)
tmp = a;
表示把 a a a 杯子的水倒进这个临时的杯子里; -
(
2
)
(2)
(2)
a = b;
表示把 b b b 杯子的水倒进 a a a 杯子里; -
(
3
)
(3)
(3)
b = tmp;
表示把临时杯子里的水倒进 b b b 杯子里; - 这三步,就实现了变量 a a a 和 b b b 的交换。
2、正确解法2:引入算术运算
#include <stdio.h>
int main() {
int a, b;
while (scanf("%d %d", &a, &b) != EOF) {
a = a + b; // (1)
b = a - b; // (2)
a = a - b; // (3)
printf("%d %d\\n", a, b);
}
return 0;
}
-
(
1
)
(1)
(1)
a = a + b;
执行完毕后,现在最新的a
的值变成原先的a + b
的值; -
(
2
)
(2)
(2)
b = a - b;
执行完毕后,相当于b
的值变成了a + b - b
,即原先a
的值; -
(
3
)
(3)
(3)
a = a - b;
执行完毕后,相当于a
的值变成了a + b - a
,即原先b
的值; - 从而实现了变量
a
和b
的交换。
3、正确解法3:引入异或运算
- 首先,介绍一下C语言中的
^
符号,代表的是异或。 - 二进制的异或,就是两个数转换成二进制表示后,按照位进行以下运算:
左操作数 | 右操作数 | 异或结果 |
---|---|---|
0 | 0 | 0 |
1 | 1 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
- 也就是对于 0 和 1,相同的数异或为 0,不同的数异或为 1。
- 这样就有了三个比较清晰的性质:
- 1)两个相同的十进制数异或的结果一定位零。
- 2)任何一个数和 0 的异或结果一定是它本身。
- 3)异或运算满足结合律和交换律。
#include <stdio.h>
int main() {
int a, b;
while (scanf("%d %d", &a, &b) != EOF) {
a = a ^ b; // (1)
b = a ^ b; // (2)
a = a ^ b; // (3)
printf("%d %d\\n", a, b);
}
return 0;
}
- 我们直接来看
(
1
)
(1)
(1) 和
(
2
)
(2)
(2) 这两句话,相当于
b
等于a ^ b ^ b
,根据异或的几个性质,我们知道,这时候的b
的值已经变成原先a
的值了。 - 而再来看最后一句话,相当于
a
等于a ^ b ^ a
,还是根据异或的几个性质,这时候,a
的值已经变成了原先b
的值。 - 从而实现了变量
a
和b
的交换。
4、正确解法4:奇淫技巧
- 当然,由于这个题目问的是交换变量后的输出,所以它是没办法知道我程序中是否真的进行了交换,所以可以干一些神奇的事情。比如这么写:
#include <stdio.h>
int main() {
int a, b;
while (scanf("%d %d", &a, &b) != EOF) {
printf("%d %d\\n", b, a);
}
return 0;
}
- 你学废了吗 🤣?
2、例题2:整数溢出
一、题目描述
先输入一个 t ( t ≤ 100 ) t (t \\le 100) t(t≤100),然后输入 t t t 组数据。每组输入为 4 个正整数 a , b , c , d ( 0 ≤ a , b , c , d ≤ 2 62 ) a,b,c,d(0 \\le a,b,c,d \\le 2^{62}) a,b,c,d(0≤a,b,c,d≤262),输出 a + b + c + d a+b+c+d a+b+c+d 的值。
二、解题思路
难度:🔴🔴⚪⚪⚪
- 这个问题考察的是对补码的理解。
- 仔细观察题目给出的四个数的范围:
[
0
,
2
62
]
[0, 2^{62}]
[0,262],这四个数加起来的和最大值为
2
64
2^{64}
264。而C语言中,
long long
的最大值为: 2 63 − 1 2^{63}-1 263−1,就算是unsigned long long
,最大值也只有 2 64 − 1 2^{64}-1 264−1。 - 但是我们发现,只有当四个数都取得最大值 2 62 2^{62} 262 时,结果才为 2 64 2^{64} 264,所以可以对这一种情况进行特殊判断,具体参考代码详解。
三、代码详解
#include <stdio.h>
typedef unsigned long long ull; // (1)
const ull MAX = (((ull)1)<<62); // (2)
int main() {
int t;
ull a, b, c, d;
scanf("%d", &t);
while (t--) {
scanf("%llu %llu %llu %llu", &a, &b, &c, &d); // (3)
if (a == MAX && b == MAX && c == MAX && d == MAX) // (4)
printf("18446744073709551616\\n"); // (5)
else
printf("%llu\\n", a + b + c + d); // (6)
}
return 0;
}
-
(
1
)
(1)
(1) 由于这题数据量较大,所有数据都需要用64位无符号整型。
ull
作为unsigned long long
的别名; -
(
2
)
(2)
(2) 用常量
MAX
表示 2 62 2^{62} 262,这里采用左移运算符直接实现 2 2 2 是幂运算;
数学 | C语言 |
---|---|
2 n 2^n 2n | 1<<n |
- 需要注意的是,由于 1 是
int
类型,所以需要对 1 进行强制转换。(ull)1
等价于(unsigned long long)1
; -
(
3
)
(3)
(3)
%llu
是无符号64位整型的输入方式; -
(
4
)
(4)
(4) 这里是对所有数都等于最大值的特殊判断,
&&
运算符的优先级低于==
,所以这里不加括号也没事; - ( 5 ) (5) (5) 由于 2 64 2^{64} 264 是无法用数字的形式输出的,所以我们提前计算机算好以后,用字符串的形式进行输出;
- ( 6 ) (6) (6) 其它情况都在 [ 0 , 2 64 − 1 ] [0, 2^{64}-1] [0,264−1] 范围内,直接相加输出即可。
- 由于这个专栏是付费专栏,可能对学生党不是很友好,所以作者经过再三思考,打算放出 300 张 一折优惠券, 先到先得。只要拿这个图片来找作者即可享受,仅限前 300 名。
- 为了适当提高一定门槛,你至少需要学会如何下载图片或者截图并且发送到微信里 🤣。
3、数据结构
- 《C语言入门100例》上的例题,如果能理解前面 25 道,那基本C语言的学习就可以告一段落了,接下来就要开始我们的数据结构的学习了。
1、什么是数据结构
- 你可能听说过 数组、链表、队列、栈、堆、二叉树、图,没错,这些都是数据结构,但是你要问我什么是数据结构,我突然就一脸懵逼了。
- 如果一定要给出一个官方的解释,那么它就是:
计算机存储、组织数据的方式。相互之间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。往往同高效的检索算法和索引技术有关。
- 是不是还不如说它是堆,是栈,是队列呢?
- 是这样的,我们学习的过程中,跳过一些不必要的概念,能够节省我们更多的时间,从而达到更好的效果,当你还在理解数据结构是什么的时候,可能人家已经知道了栈有哪些操作了。
2、数据结构和算法的关系
- 很多同学搞不明白,数据结构与算法有哪些千丝万缕的关系?甚至有些同学以为算法里本身就包含了数据结构。
- 数据结构主要讲解数据的组织形式,比如链表,堆,栈,队列。
- 而算法,则注重的是思想,比如链表的元素怎么插入、删除、查找?堆的元素怎么弹出来的?栈为什么是先进后出?队列又为什么是先进先出?
- 讲得直白一点,数据结构是有实体的,算法是虚拟的;数据结构是物质上的,算法是精神上的。当然,物质和精神 缺一不可。
3、数据结构概览
- 周末花了一个下午整理的思维导图,数据结构:
- 常用的一些数据结构,各自有各自的优缺点,总结如下:
a、数组
内存结构:内存空间连续
实现难度:简单
下标访问:支持
分类:静态数组、动态数组
插入时间复杂度: O ( n ) O(n) O(n)
查找时间复杂度: O ( n ) O(n) O(n)
删除时间复杂度: O ( n ) O(n) O(n)
b、字符串
内存结构:内存空间连续,类似字符数组
实现难度:简单,一般系统会提供一些方便的字符串操作函数
下标访问:支持
插入时间复杂度: O ( n ) O(n) O(n)
查找时间复杂度: O ( n ) O(n) O(n)
删除时间复杂度: O ( n ) O(n) O(n)
c、链表
内存结构:内存空间连续不连续,看具体实现
实现难度:一般
下标访问:不支持
分类:单向链表、双向链表、循环链表、DancingLinks
插入时间复杂度: O ( 1 ) O(1) O(1)
查找时间复杂度: O ( n ) O(n)以上是关于❤️两万字《算法 + 数据结构》全套路线❤️(建议收藏)的主要内容,如果未能解决你的问题,请参考以下文章 ❤️《画解数据结构》两万字,十张动图,画解双端队列❤️(建议收藏)
❤️《画解数据结构》两万字,十张动图,画解双端队列❤️(建议收藏)
❤️思维导图整理大厂面试高频数组: 两万字详解各种数组求和(建议收藏)❤️
❤️思维导图整理大厂面试高频数组: 两万字详解各种数组求和(建议收藏)❤️