这几天疯狂面试,每天都接到新的面试,是时候复习一下我的python基础了,虽然平时做项目的时候用的都是一些库,加上自己时常不注重基础,以至于面试的时候有的非常详细的基础部分反倒扯后腿,被某宇宙大厂面试官建议虽然可能进公司之后不需要这么细节,但是面试的时候还是应该更熟悉基础。(心痛
所以我在这里总结一些常用的基础,和一些非常常用的数据结构算法代码,自己复习的同时也记录一下。
以下基础用一些题目进行辅助理解
面试经典 150 题 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台
1.python数据类型
在 Python 中,数据类型可以分为基本数据类型和容器数据类型。以下是对 Python 中主要 9 种数据类型的详细讲解:
1.
Int(整型)
- 描述
:整型(
int
)用于表示整数,支持正数、负数和零。Python 中的整型可以表示任意大小的整数,内存大小仅受限于机器的可用内存。 - 操作
:- 加法、减法、乘法、除法
- 幂运算:
**
- 整数除法:
//
- 取模:
%
2.
Float(浮点型)
- 描述
:浮点型(
float
)用于表示带有小数部分的数字,符合 IEEE 754 标准的双精度浮点数。浮点型通常用于需要精度较高的数值运算。- 符号位(Sign Bit)
:用于表示数值的正负。
0
表示正数,
1
表示负数。 - 指数部分(Exponent)
:表示浮点数的数量级。它的值通过偏移量(bias)来存储,通常是
127
对于 32 位浮点数(单精度)和
1023
对于 64 位浮点数(双精度)。 - 尾数部分(Mantissa/Significand)
:表示有效数字部分,通常是一个二进制小数。尾数部分的表示是归一化的,即最前面为 1 的二进制数默认为 1,所以通常不需要显式存储。
- 符号位(Sign Bit)
- 操作
:- 加法、减法、乘法、除法
- 幂运算:
**
- 科学计数法表示:
1.23e4
表示
1.23 × 10^4
3.
Bool(布尔型)
- 描述
:布尔型(
bool
)用于表示真值(True 和 False)。它是整型的子类,其中
True
等价于
1
,
False
等价于
0
。 - 操作
:- 逻辑运算:
and
,
or
,
not
- 比较运算:
==
,
!=
,
>
,
<
,
>=
,
<=
- 逻辑运算:
4.
Str(字符串)
- 描述
:字符串(
str
)用于表示文本数据。字符串是不可变的数据类型,定义时可以使用单引号、双引号或三引号(用于多行字符串)。 - 操作
:- 字符串拼接:
+
- 字符串重复:
*
- 索引和切片:
name[0]
,
name[1:4]
- 字符串方法:
lower()
,
upper()
,
replace()
,
find()
- 字符串拼接:
示例字符串
s = “Hello, World! Welcome to Python.”
1. 获取字符串长度
length = len(s)
2. 字符串拼接
s1 = “Hello”
s2 = “World”
s3 = s1 + “, “ + s2 + “!”
3. 字符串重复
repeated = s1 * 3
4. 字符串切片
sub1 = s[0:5]
sub2 = s[7:]
sub3 = s[::2]
5. 字符串查找
position = s.find(“World”)
position_index = s.index(“World”)
6. 字符串替换
new_s = s.replace(“World”, “Python”)
7. 字符串拆分
words = s.split()
comma_split = s.split(“,”)
8. 字符串连接
joined_s = “ “.join(words)
9. 字符串大小写转换
upper_s = s.upper()
lower_s = s.lower()
capitalized_s = s.capitalize()
title_s = s.title()
swapped_s = s.swapcase()
10. 去除空白字符
stripped_s = s.strip()
lstripped_s = s.lstrip()
rstripped_s = s.rstrip()
11. 字符串判断
starts_with_hello = s.startswith(“Hello”)
ends_with_python = s.endswith(“Python”)
is_alnum = s1.isalnum()
is_alpha = s1.isalpha()
is_digit = s1.isdigit()
12. 字符串格式化
formatted_s = “My name is {} and I am {} years old.”.format(“Alice”, 25)
formatted_f_string = f”My name is {‘Alice’} and I am {25} years old.”
打印所有结果
print(f”Length of the string: {length}”)
print(f”Concatenation: {s3}”)
print(f”Repeated string: {repeated}”)
print(f”Substring [0:5]: {sub1}”)
print(f”Substring [7:]: {sub2}”)
print(f”Substring with step 2: {sub3}”)
print(f”Position of ‘World’: {position}”)
print(f”Replaced string: {new_s}”)
print(f”Split by space: {words}”)
print(f”Split by comma: {comma_split}”)
print(f”Joined string: {joined_s}”)
print(f”Upper case: {upper_s}”)
print(f”Lower case: {lower_s}”)
print(f”Capitalized: {capitalized_s}”)
print(f”Title case: {title_s}”)
print(f”Swapped case: {swapped_s}”)
print(f”Stripped string: {stripped_s}”)
print(f”Left stripped string: {lstripped_s}”)
print(f”Right stripped string: {rstripped_s}”)
print(f”Starts with ‘Hello’: {starts_with_hello}”)
print(f”Ends with ‘Python’: {ends_with_python}”)
print(f”Is alphanumeric: {is_alnum}”)
print(f”Is alphabetic: {is_alpha}”)
print(f”Is digit: {is_digit}”)
print(f”Formatted string: {formatted_s}”)
print(f”Formatted f-string: {formatted_f_string}”)
1 |
|
创建字典
my_dict = {“name”: “Alice”, “age”: 25}
访问值
print(my_dict[“name”]) # 输出: Alice
添加/更新项
my_dict[“age”] = 26
my_dict[“city”] = “New York”
删除项
del my_dict[“city”]
删除并返回项
age = my_dict.pop(“age”)
print(age) # 输出: 26
删除并返回项
key, value = my_dict.popitem()
print(key, value) # 输出: name Alice
获取值
age = my_dict.get(“age”, “N/A”)
print(age) # 输出: N/A
清空字典
my_dict.clear()
键的视图
my_dict = {“name”: “Alice”, “age”: 25}
keys = my_dict.keys()
print(keys) # 输出: dict_keys([‘name’, ‘age’])
值的视图
values = my_dict.values()
print(values) # 输出: dict_values([‘Alice’, 25])
项的视图
items = my_dict.items()
print(items) # 输出: dict_items([(‘name’, ‘Alice’), (‘age’, 25)])
更新字典
my_dict.update({“city”: “New York”, “country”: “USA”})
检查键是否存在
print(“name” in my_dict) # 输出: True
获取键的数量
num_items = len(my_dict)
print(num_items) # 输出: 3
1 |
|
常用数据类型对比
列表(List) vs 元组(Tuple) vs 集合(Set)vs字典(DICT)
特性 | 列表(List) | 元组(Tuple) | 集合(Set) | 字典(Dict) |
---|---|---|---|---|
定义 | 用方括号 [] 定义 | 用圆括号 () 定义 | 用花括号 {} 定义 | 用花括号 {} 定义,键值对 key: value |
可变性 | 可变(可以修改、添加、删除元素) | 不可变(不能修改、添加、删除元素) | 可变(可以修改、添加、删除元素) | 可变(可以修改、添加、删除键值对) |
有序性 | 有序(元素顺序保持) | 有序(元素顺序保持) | 无序(不保证元素顺序) | 无序(保持插入顺序) |
支持重复 | 支持重复元素 | 支持重复元素 | 不支持重复元素 | 键不支持重复,值支持重复 |
操作 | 支持丰富的操作:append(), extend(), remove(), pop(), 切片等 | 支持基本操作:切片, 解包等 | 支持集合运算:并集 ` | ,交集 & ,差集 -` |
性能 | 对于大规模数据,性能较低(因为可变性) | 性能较高(由于不可变性,通常比列表快) | 由于哈希表实现,查找操作非常高效 | 查找、插入和删除操作平均时间复杂度为 O(1) |
用途 | 适用于需要频繁修改、添加、删除的场景 | 适用于数据不需要修改的场景,例如作为字典的键 | 适用于去重操作和集合运算 | 适用于键值对映射,如存储对象的属性等 |
示例 | my_list = [1, 2, 3, 4] | my_tuple = (1, 2, 3, 4) | my_set = {1, 2, 3} | my_dict = {“name”: “Alice”, “age”: 25} |
2.常用的数据结构
顺序表
是一种线性数据结构,其元素顺序存储在一块连续的内存空间中。在 Python 中,顺序表通常由列表(
list
)来实现。
顺序表的基本操作包括插入、删除、查找和遍历。顺序表的插入和删除操作包括在表的头部、尾部和任意位置进行插入和删除。查找操作包括遍历查找和二分查找。
1.
数组(Array)——顺序表
- 定义
: 数组是一种线性数据结构,由一组连续的内存位置组成,其中每个元素可以通过索引直接访问。 - 特点
:- 元素按顺序存储,支持随机访问。
- 大小固定(静态数组)。
- 用法示例
:
1 |
|
2.
链表(Linked List)——顺序表
链表是一种常用的动态数据结构,适合频繁的插入和删除操作。链表的每个元素称为一个节点,节点包含数据和指向下一个节点的指针。在链表中,元素的插入和删除不需要移动其他元素,但需要调整指针的指向。
可以使用链表来实现与顺序表(列表)类似的操作,如头插、尾插、任意位置插入、头删、尾删、任意位置删除、遍历查找等。
- 定义
: 链表是一种线性数据结构,其中每个元素称为节点,节点包含数据和指向下一个节点的指针。 - 特点
:- 支持动态内存分配。
- 插入和删除操作在链表中更高效。
- 用法示例
:
1 |
|
这里遇到最多的算法题反转链表,力扣面试150-92反转链表,
+ #### 步骤解析(这个题与普通反转列表的区别就是普通的全部都反转了无需考虑前后点,这个也只是多了一步确认从哪开始反转)
+ **定位反转的起点**
:通过遍历链表,找到位置
`left`
的节点,即反转部分的起点。这个节点的前一个节点我们称为
`prev`
。
+ **反转指定区间的节点**
:使用三个指针进行反转操作,分别是
`prev`
(当前节点的前一个节点),
`current`
(当前节点),以及
`next`
(当前节点的下一个节点)。
+ **连接反转后的部分**
:将反转后的部分连接回原链表。
`prev`
指向反转后的头节点,反转区间的末尾节点连接到
`right`
位置后的第一个节点。
+ ```
class ListNode:
def __init__(self, value=0, next=None):
self.value = value
self.next = next
def reverse_between(head, left, right):
if not head or left == right:
return head
# 创建一个x,方便处理头节点为left的情况
x = ListNode(0)
x.next = head
prev = x
#移动 prev 到 left 的前一个节点
for _ in range(left - 1):
prev = prev.next
#开始反转
y = prev.next
next = None
for _ in range(right - left):
next = y.next
#将 y 节点的下一个节点存储在 next 中。next 变量保存了即将被反转的节点。
y.next = next.next
#设置为 next.next,即跳过 next 节点,
#使 y 节点直接连接到 next 节点的下一个节点。将 next 从当前链表中拆出来。
next.next = prev.next
#将 next 节点的下一个指针 next.next 指向 prev.next,即链表中反转部分的当前头部。
#这样,next 节点就成为了反转部分的新头部。
prev.next = next
#更新 prev.next 指向新的头部 next,即反转后的链表部分。
#prev 节点的 next 就连接到了新的头节点上,完成了反转。
return dummy.next
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
### 3\.
**栈(Stack)**
* **定义**
: 栈是一种线性数据结构,遵循后进先出(LIFO)的原则。
* **特点**
:
+ 插入和删除操作只能在栈顶进行。
+ 用于处理逆序问题(如括号匹配、逆波兰表达式计算)。
* **用法示例**
:力扣面试150\-20有效的括号(注意这道题出现在两次面试中,不得不说力扣这个刷题的确实很管用)
![](https://i-blog.csdnimg.cn/direct/0e4224744a6149098ecbf3f61ffe4471.png)
class Solution:
def isValid(self, s: str) -> bool:
dic = {‘{‘: ‘}’, ‘[‘: ‘]’, ‘(‘: ‘)’, ‘?’: ‘?’}
#这里用字典匹配后续的括号,前后括号
stack = [‘?’]
#到时候如果最后只剩下?了证明就是对滴
for c in s:
if c in dic:
stack.append(c)
elif dic[stack.pop()] != c:
return False
return len(stack) == 1
1 |
|
本题目可以使用最小堆(优先级队列)来合并链表。(这个题目是个困难题,印象中好像某个大厂出现过原题,我当时写的啥也不是,这题目我需要再斟酌,有大佬有更好的思路拜托大佬们评论区指导我一下谢谢谢谢!)
5.
树(Tree)
- 定义
: 树是一种非线性数据结构,由节点组成,通常具有层次结构。每个节点包含数据,并可以有零个或多个子节点。 - 特点
:- 特殊的树结构如二叉树、二叉搜索树、AVL 树等。
- 常用于表示层次关系(如文件系统、组织结构)。
- 用法示例
:树真的超级常用递归,完全可以在树的这里好好学习一番递归函数,因为他的性质很合适
1 |
|
还有就是二叉树的各种遍历,需要跟排序算法一样了如指掌,实在不会背过都可以(开玩笑的哈哈),以这个为延申可以做很多题目。
1 |
|
6.
图(Graph)
- 定义
: 图是一种非线性数据结构,由顶点和边组成。顶点通过边相互连接。 - 特点
:- 图可以是有向图或无向图,有权图或无权图。
- 常用于网络路由、社交网络分析等。
- 用法示例
:
1 |
7.
堆(Heap)
- 定义
: 堆是一种特殊的树形数据结构,满足堆属性。最大堆中每个节点的值都大于或等于其子节点的值,最小堆中每个节点的值都小于或等于其子节点的值。 - 特点
:- 常用于实现优先队列。
- 支持快速获取最大值或最小值。
- 用法示例
:堆排序谁懂!超级容易出现的面试题目,冲冲冲!
1 |
8.
散列表(Hash Table)
- 定义
: 散列表是一种数据结构,通过将键映射到值来实现键值对的存储。它使用哈希函数将键映射到数组中的特定位置。 - 特点
:- 支持快速的查找、插入和删除操作。
- Python 中的字典(
dict
)实现了散列表。
3.常用的关键字集锦
关键字 | 作用 | 使用场景 | 补充说明 |
---|---|---|---|
and | 逻辑与 | 用于两个条件都为真时,结果为真 | 可用于条件组合 |
or | 逻辑或 | 两个条件中只要一个为真,结果为真 | 可用于条件组合 |
not | 逻辑非 | 将布尔值取反 | 可用于布尔值判断 |
if | 条件判断 | 条件为真时执行代码块 | 常与 else 、 elif 结合 |
elif | 额外条件 | if 条件不满足时的额外判断 | 通常跟在 if 之后 |
else | 备用方案 | 当 if 和 elif 条件不满足时执行 | 用于条件语句和异常处理 |
for | 循环 | 遍历序列或可迭代对象 | 常与 range() 结合使用 |
while | 循环 | 当条件为真时,重复执行代码块 | 适合未知循环次数的场景 |
continue | 跳过当前循环 | 跳过当前循环的剩余部分,进入下一次循环 | 主要用于循环控制 |
break | 终止循环 | 立即终止当前循环 | 适合提前结束循环 |
pass | 占位符 | 什么也不做,用于占位 | 用于未实现的代码块 |
try | 异常捕获 | 用于捕获可能出现的异常 | 常与 except 、 finally 结合 |
except | 异常处理 | 在捕获异常后执行的代码块 | 用于处理异常 |
finally | 异常清理 | 无论是否有异常,都会执行 | 常用于资源清理 |
raise | 抛出异常 | 主动引发一个异常 | 可自定义异常类型 |
import | 导入模块 | 导入外部模块或库 | 常与 from 结合 |
def | 定义函数 | 定义一个函数或方法 | 函数体内使用 return 返回值 |
return | 返回值 | 从函数中返回一个值并结束函数 | 用于结束函数的执行 |
class | 定义类 | 定义一个类 | 类定义中包含属性和方法 |
lambda | 匿名函数 | 定义一个简短的匿名函数 | 通常用于简单函数表达式 |
global | 声明全局变量 | 声明一个变量为全局变量 | 用于函数内部修改全局变量 |
nonlocal | 声明非局部变量 | 用于嵌套函数中,声明外层函数的变量 | 修改闭包作用域中的变量 |
in | 成员判断 | 检查一个值是否在序列或集合中 | 常用于 if 语句 |
is | 身份判断 | 判断两个对象是否为同一个对象 | 比较对象的内存地址 |
None | 空值 | 表示什么都没有 | NoneType 的实例 |
assert | 断言 | 用于调试 | 条件为 False 时触发异常 |
with | 上下文管理 | 简化资源管理 | 常与 open 一起使用 |
yield | 生成器 | 定义一个生成器函数 | 函数会暂停并返回值 |
4.常用的函数列举
函数 | 作用 | 使用场景 | 补充说明 |
---|---|---|---|
next() | 获取迭代器的下一个元素 | 手动遍历迭代器 | 如果没有更多元素,会抛出 StopIteration 异常 |
len() | 返回对象的长度 | 计算序列或集合的元素数量 | 常用于 str 、 list 、 tuple 等 |
range() | 返回一个范围对象 | 生成一个数字序列 | 通常用于循环 |
enumerate() | 返回枚举对象 | 在循环中获取索引和值 | 常用于 for 循环 |
zip() | 打包可迭代对象 | 将多个序列打包成元组的迭代器 | 用于并行遍历 |
map() | 函数映射 | 将函数应用于可迭代对象的每个元素 | 返回一个迭代器 |
filter() | 过滤元素 | 根据条件筛选可迭代对象的元素 | 返回满足条件的元素 |
sorted() | 返回排序后的列表 | 对序列进行排序 | 不修改原序列,返回新的列表 |
min() | 返回最小值 | 查找序列或集合中的最小元素 | 适用于 str 、 list 等 |
max() | 返回最大值 | 查找序列或集合中的最大元素 | 适用于 str 、 list 等 |
sum() | 计算总和 | 求序列或集合中元素的总和 | 仅适用于数字类型 |
abs() | 绝对值 | 计算数字的绝对值 | 返回非负数 |
all() | 全真判断 | 判断可迭代对象的所有元素是否为真 | 如果全为真,返回 True |
any() | 存在真判断 | 判断可迭代对象中是否有任意一个元素为真 | 如果有一个为真,返回 True |
type() | 返回对象类型 | 获取对象的类型 | 常用于检查对象类型 |
isinstance() | 检查实例 | 判断对象是否为特定类的实例 | 用于类型判断 |
id() | 返回对象唯一标识 | 获取对象的内存地址 | 常用于比较对象身份 |
注意其中next面试的时候被问到,我回答的不太靠谱,这里涉及到迭代器和生成器的原理,我在这里补充一下:
5.迭代器和生成器
1. 迭代器原理
迭代器(Iterator)是一种用于遍历数据结构中元素的设计模式,能够按照顺序访问容器中的每个元素,而不需要了解容器的底层实现。迭代器提供了一种统一的接口来访问容器中的元素。
迭代器的核心特征
:
- 封装
:迭代器封装了数据的遍历过程,不需要暴露容器的内部结构。 - 状态保存
:迭代器能够在遍历过程中保存状态,以便在需要时恢复。
实现原理
:
- 迭代器协议
:在 Python 中,迭代器需要实现两个关键方法:__iter__()
:返回迭代器对象自身,通常可以直接返回
self
。__next__()
:返回容器中的下一个元素。如果没有更多元素可以返回,则抛出
StopIteration
异常,表示迭代已结束。
2. Python 中的迭代器与可迭代对象
在 Python 中,有两种重要的概念:
- 可迭代对象(Iterable)
:指那些可以返回迭代器的对象,如列表、元组、字典、集合、字符串等。可迭代对象实现了
__iter__()
方法,但不一定实现
__next__()
方法。 - 迭代器(Iterator)
:指那些实现了
__iter__()
和
__next__()
方法的对象。迭代器不仅是可迭代对象,还可以通过
next()
函数获取下一个元素。 - 迭代器(iterator)一定是可迭代对象(iterable),可迭代对象不一定是迭代器
可迭代对象
:
- 列表
(
list
) - 元组
(
tuple
) - 字典
(
dict
) - 集合
(
set
) - 字符串
(
str
)
迭代器
:
- 生成器
(使用
yield
的函数) - 自定义的迭代器类
(如上述示例)
特性 | 列表 (List) | 迭代器 (Iterator) | 生成器 (Generator) |
---|---|---|---|
定义 | 有序的元素集合,可变的容器类型 | 实现了 __iter__() 和 __next__() 方法的对象 | 使用 yield 关键字创建的特殊迭代器 |
创建 | 使用方括号创建,如 [1, 2, 3] | 使用 iter() 函数创建,如 iter(lst) | 使用生成器函数创建,如 def gen(): yield … |
存储方式 | 存储所有元素在内存中 | 按需生成元素,不需一次性存储所有元素 | 按需生成元素,不需一次性存储所有元素 |
访问方式 | 支持随机访问,如 lst[0] | 只能逐个访问,通过 next() 函数 | 只能逐个访问,通过 next() 函数 |
内存使用 | 存储所有元素,占用更多内存 | 节省内存,按需生成元素 | 节省内存,按需生成元素 |
迭代功能 | 可以被 for 循环遍历 | 可以被 for 循环遍历 | 可以被 for 循环遍历 |
重复使用 | 可以多次遍历 | 遍历一次后不能重用,需要重新创建 | 遍历一次后不能重用,需要重新创建 |
性能 | 遍历速度快,但内存消耗大 | 性能较好,但每次调用 next() 可能略慢 | 性能较好,特别适合处理大数据 |
示例 | lst = [1, 2, 3] | it = iter([1, 2, 3]) | def gen(): yield 1; yield 2; yield 3 |
3. 生成器原理
生成器(Generator)是 Python 中一种特殊的迭代器,用于按需生成值。与一次性创建所有元素的数据结构(如列表或元组)不同,生成器每次迭代时只生成下一个值,因此更节省内存并支持无限序列或大量数据流的操作。
2. 生成器的关键特性
- 延迟计算
:生成器不会一次性计算所有结果,而是每次需要时逐步计算并生成值。这种按需计算的方式可以节省内存。 - 状态保持
:生成器在每次
yield
语句执行后会保存其执行状态,下一次调用时会从上次暂停的地方继续执行。 - 内存效率
:生成器在生成值时只需存储当前状态,相比于列表或元组,内存消耗较小。
3.
yield
关键字
- 定义生成器函数
:
yield
关键字用于定义生成器函数。生成器函数是一种特殊的函数,当执行到
yield
语句时,函数的执行会暂停,并返回
yield
后面的值。函数的状态会被保存,每次迭代时从上次暂停的地方继续执行。
以下代码创造一个生成器
1 |
|