Python算法题基础入门:基础语法快速掌握
我发现csdn上面没有那种比较系统的编程和算法讲解,所以我准备先用两到三篇文章介绍一下python的基础语法和常用api,然后再通过力扣题目,灵神的题单和codeforces的简单题目介绍一些基础的算法,然后坚持更新codeforce一些比赛的题解和一些有意思的题目,我会讲的尽可能细节,不想用py的也可以关注我,之后更新的题解我会用java,cpp,go都写一遍。有什么相关建议也欢迎讨论
之后我准备更新的有:《Python写算法基础(二.常用API)》《算法入门:数组与字符串》《算法入门:哈希表》《算法入门:双指针》,《滑动窗口算法》,《二分查找算法和应用》,《位运算的运用》,《前缀和的运用》,《动态规划算法》,….等,有的主题可能不止一篇文章,然后再会讲解一些数据结构和更加复杂的东西比如树状数组,字典树,图论相关。我也算是一个算法新手,坚持更新内容,一起学习和讨论。
本文比较适合有点编程基础的人,比如学过java,c,cpp的,不太适合刚入门编程的小白,主要在讲一些基础概念和简单的使用方法,一些经常用不到的也不会讲,比如元组这种,但可以帮助快速入门py,看完我的文章就可以打codeforce的div1比赛(bushi)
基础语法
一,输入和输出
输出:
python里面有很多种函数可以用来输出内容,但是刷算法题的话,使用print一般就够输出大多数结果了
#最基础的输出,注意这个默认打印结束后换行
print(1)
#上面的输出等于下面的
print(1, end = '\n')
#如果不换行就是
print(1, end = ' ')
#把两个字符输出到同一行
s_1 = 'abc'
s_2 = 'def'
#逗号默认是空格
print(s_1,s_2)
#加其他字符,字符串
print(s_1, '+', s_2)
还有一种是Python 3.6 引入的格式化字符串字面值(也称为 f-string)来生成一个字符串
(刷算法题目的话,用的比较少)
# 假设我们有两个变量 num1 和 num2
num1 = 5
num2 = 10
# 使用 f-string 执行算术运算并格式化输出
print(f"The sum of {num1} and {num2} is {num1 + num2}.")
输入:
输入如果不加类型转换的话,默认是字符串类型
# 基本输入,获取用户输入的字符串
input_val = input("请输入一些内容: ")
# 输入转换为整数,如果转换失败将抛出 ValueError 异常
nums_1 = int(input("请输入一个整数: "))
# 输入转换为浮点数,如果转换失败将抛出 ValueError 异常
nums_2 = float(input("请输入一个浮点数: "))
# 输入转换为字符串(通常不必须,因为 input() 直接返回的就是字符串)
string = input("请输入一个字符串: ")
# 获取单个字符,通过输入一个字符串然后取第一个字符
character = input("请输入一个字符: ")
print(input_val)
print(nums_1)
print(nums_2)
print(string)
print(character)
对于一行的输入
先介绍一下这个split()方法
# 使用 split() 方法分割字符串,默认按空白字符分割
st1 = "1 2 3"
str_split_1 = st1.split()
print(str_split_1) # 输出: ['1', '2', '3']
# 使用 split() 方法分割字符串,指定分隔符和分割次数
st2 = '1,2,3'
str_split_2 = st2.split(',', 1)
print(str_split_2) # 输出: ['1', '2,3']
利用 split()
方法处理用户输入的一列数字:
# 读取用户输入并使用空格分割成列表
input_values = input("请输入一列数字,用空格分隔: ").split()
# 将字符串列表转换为整数列表
int_list = [int(value) for value in input_values]
print(int_list) # 输出转换后的整数列表
如果输入的数字是两三个(不是很多的情况),那么可以这么写,这是列表推导式
n, m = [int(n) for n in input().split()]
如果输入的是一串数字,那么问题现在就变成了怎么把一个列表转换类型
input_value = input().split()
#转换一般可以这么写
n = len(input_value)
int_list1 = [0]*n
for i in range(n):
int_list1[i]=int(input_value[i])
#使用列表推导式就是
int_list2 = [int(n) for n in input_value]
print(int_list1)
print(int_list2)
所以最终可以把输入简化成下面这样,如果是小数就用float
input_value = [int(n) for n in input().split()]
print(input_value)
还有就是一个map方法,这个是非常常用的,基础语法如下:
map(function, iterable, ...)
作用是将后面这个列表或者是元组iterable里面的元素全部使用前面的方法
注意:map()
函数在 Python 2 中返回列表,但在 Python 3 中返回迭代器,需要用 list()
来转换。
那么就可以用这个map函数对列表进行类型转换,那么就可以有(这是py3最常用的输入)
input_value = list(map(int, input().split()))
print(input_value)
二,运算符
算术运算符
+
:加-
:减*
:乘/
:除(浮点数结果)//
:整除(两个数相除的结果向下取整)%
:取模(余数)**
:幂(指数)主要注意的就是python中的除有两种,整除和除法:
a = 10
b = 5
# 除法(浮点数结果)
division = a / b # 2.0
print("除法结果:", division)
# 整除(两个数相除的结果向下取整)
floor_division = a // b # 2
print("整除结果:", floor_division)
# 幂(指数)
power = a ** b # 100000
print("幂结果:", power)
比较运算符
==
:等于!=
:不等于>
:大于<
:小于>=
:大于等于<=
:小于等于位运算符
(刚入门的可以跳过,直接看后面的,具体方法之后讲算法的时候会具体出一节,现在讲个大概)
位运算速度是比常规的算数运算快很多的,因为它们在硬件层面上执行,不需要额外的数据类型转换或复杂的数学处理。而且是直接二进制运算,不需要额外内存。当然也可以用来炫技
&
:按位与|
:按位或^
:按位异或~
:按位取反<<
:左移>>
:右移下面这代码就是简单的位运算还有详细的解释:
a = 14 # 二进制表示为 1110
b = 3 # 二进制表示为 0011
# 按位与 (&)
bitwise_and = a & b # 结果为 2,二进制表示为 0010
print("按位与结果:", bitwise_and)
# 按位或 (|)
bitwise_or = a | b # 结果为 15,二进制表示为 1111
print("按位或结果:", bitwise_or)
# 按位异或 (^)
bitwise_xor = a ^ b # 结果为 13,二进制表示为 1101
print("按位异或结果:", bitwise_xor)
# 按位取反 (~)
bitwise_not = ~a # 结果为 -15,二进制表示反转后需要考虑补码表示
print("按位取反结果:", bitwise_not)
# 左移 (<<)
left_shift = a << 2 # 结果为 56,二进制表示为 111100
print("左移结果(左移2位):", left_shift)
# 右移 (>>)
right_shift = b >> 1 # 结果为 1,二进制表示为 0001
print("右移结果(右移1位):", right_shift)
三,列表
列表
(嗯…感觉是不是得先说循环,不过我觉得大伙们都应该看得懂)
列表是一种可变的,可以包含任意类型的元素,元素可以被修改、添加或删除,就是类似于java中的ArrayList<>()
一般来说,确定了list的长度后就不需要append方法进行添加,那么可以这么创建列表
length = int(input())
my_list = []*length
print(my_list)
下面这些就是列表的常用操作,这些方法不会创建新的列表,都是对原来的列表进行的操作
append(x)
:在列表末尾添加元素x。remove(x)
:删除列表中的元素x。insert(index, x)
:在指定位置插入元素x。extend(iterable)
:将一个可迭代对象的元素添加到列表末尾。这个可以添加的可以是元组,列表,字典的键和值
sort(key=None, reverse=False)
:对列表进行排序。这个key函数一般不会用到,一般默认值是None,是根据某些内容进行排序的,比如你有一个字符串列表,你想根据字符串的长度进行排序:
words = ['banana', 'apple', 'cherry', 'date']
words.sort(key=len)
print(words) # 输出: ['date', 'apple', 'banana', 'cherry']
后面这个reverse的默认值是False,表示升序排列,如果改成True,就是降序排列
reverse()
:反转列表中的元素顺序。这个反转列表在一般算法题里面用的很多,知道这个方法就可以很简便。
下面代码就是基础的操作,知道这个操作具体是干什么的就行,之后遇到实际的题目再灵活使用
# 初始化一个列表
my_list = [1, 2, 3]
# append(x):在列表末尾添加元素x
my_list.append(4)
print("使用 append 后的列表:", my_list)
# remove(x):删除列表中的元素x
my_list.remove(2)
print("使用 remove 后的列表:", my_list)
# insert(index, x):在指定位置插入元素x
my_list.insert(1, 5)
print("使用 insert 后的列表:", my_list)
# extend(iterable):将一个可迭代对象的元素添加到列表末尾
my_list.extend([5, 6])
print("使用 extend 后的列表:", my_list)
# sort(key=None, reverse=False):对列表进行排序
my_list.sort() # 默认升序排序
print("使用 sort 排序后的列表:", my_list)
# reverse():反转列表中的元素顺序
my_list.reverse()
print("使用 reverse 反转后的列表:", my_list)
二维列表
这个就是类似于java中的List<List<Integer>> matrix = new ArrayList<>();这个跟二维数组是不太一样的,它可以是不规则的,比如第一行2个元素,第二行3个元素,但一般没这种情况
(大致了解一下这种二维的就行,之后我会专门讲一篇关于网格图相关的)
二维列表不能跟普通列表那么创建
(这个我觉得要注意一下,因为我刚学的时候就这么写的)
n, m = 3, 4
# matrix = [[0]*n]*m
# print(my_list)
#如果像是上面这么创建的话,那么每一行的列表就不再是独立的
#正确的创建方法,使用列表推导式
matrix = [[0 for _ in range(m)] for _ in range(n)]
#这个表示的就是一行有m个数字,一共有n行
先讲二维列表的输入,假设题目中是一个n*m的矩阵需要输入进来,那么可以这样写:
input_matrix = []
n, m = [int(n) for n in input().split()]
for _ in range(n):
row = list(map(int, input().split()))
input_matrix.append(row)
#遍历成一行
print(input_matrix)
#换行
print()
#遍历成矩阵形式
for row in input_matrix:
print(row)
四,字典和集合
字典和set具体怎么实现的涉及到数据结构,这里暂时只讲功能,目的是为了写算法题,具体的应用之后出关于哈希表相关的算法题的时候再说
字典
这个跟哈希表类似,或者就可以直接理解成哈希表,小白可能不懂哈希表,我这里找了一篇阅读量高的:来吧!一文彻底搞定哈希表!_哈希表庆哥-CSDN博客每个元素都是一个键值对,可以理解成java中的Map<>map=new HashMap<>()其中键是唯一的,里面值的类型都是可以的,也可以是字符和字符串,当然一般字典的功能是用来计数
字典,也就是哈希表的经典用法就是统计出现次数:
#字典的创建
dict = {}
nums = [1,2,2,3,4]
for n in nums:
if n in dict:
dict[n] += 1
else:
dict[n] = 1
print(dict)#{1: 1, 2: 2, 3: 1, 4: 1}
字典的常用操作有
get(key, default=None)
:获取指定键的值,如果键不存在,则返回默认值。clear()
:清空字典keys()
: 返回一个包含字典所有键的视图。values()
: 返回一个包含字典所有值的视图。下面是遍历字典还有字典的常用操作:
# 使用字典字面量创建一个字典
my_dict = {'a': 1, 'b': 2, 'c': 3}
# 打印整个字典
print("初始字典:", my_dict)
# 遍历所有键
print("\n遍历所有键:")
for key in my_dict:
print(key, end = ' ')
# 遍历所有值
print("\n遍历所有值:")
for value in my_dict.values():
print(value, end = ' ')
# 遍历所有键值对
print("\n遍历所有键值对:")
for key, value in my_dict.items():
print(f"键: {key}, 值: {value}")
# 使用 get 方法获取键的值
value = my_dict.get('a', '默认值')
print(value, end = ' ')
my_dict.clear()
print("\n",my_dict)
一些更加复杂的用法到时候碰到实际题目再进行求解
集合
这个,嗯…就是类似于java中的Set<>set=new HashSet<>(),我的理解是只有键但没有值的字典,往里面添加各种数字后它会自动去重,比如往里面添加1,1,2,输出它就会显示1,2,创建方法跟字典一样的,直接上代码:
my_set = {1, 2, 3}
my_set.add(3)
my_set.add(4)
print(my_set)#{1, 2, 3, 4}
使用set()方法对列表去重
my_list =[1,1,1,2,3,4,5,2,3,2]
set_list = set(my_list)
print(set_list)#{1, 2, 3, 4, 5}
五,循环
range()
py中的for循环一般是搭配range()函数的,
range()函数一般有三个参数:
起始值 :序列的起始整数(默认为 0)。
结束值 :序列的结束整数(不包括该值)。
步长:序列中相邻两个整数之间的差(默认为 1)。
里面只写一个数字就表示结束值
具体的直接上代码:
#默认起点是0,开始循环到5但不包括5,每次默认加一
for i in range(5):
print(i, end = ' ')#0 1 2 3 4
print()#换行
#起点为1,开始循环到5但不包括5,每次默认加一
for i in range(1,5):
print(i, end = ' ')#1 2 3 4
print()
#起点为2,开始循环到10但不包括10,每次加2
for i in range(2,10,2):
print(i, end = ' ')#2 4 6 8
#也可以反向遍历,这个用的也挺多的
for i in range(5,0,-1)
print(i, end = ' ')#5 4 3 2 1
遍历列表
可以用range遍历也可以直接用类似其他语言中的for each遍历
my_list = [1,2,3,4,5]
#用range()遍历
for i in range(len(my_list)):
print(my_list[i], end= ' ')#1 2 3 4 5
print()
#直接遍历,这里的i表示list中的值
for i in my_list:
print(i, end = ' ')#1 2 3 4 5
字典和集合中也讲了相关遍历操作这里就不说了
while()
这个就可以理解成满足条件后就退出循环
count = 0
# 条件为 True,循环将继续执行
while count < 5:
print(count)
count += 1 # 修改条件变量,否则可能导致无限循环
还有一些跟循环有关的方法,列表递推式等我就在下一篇文章《Python写算法基础(二.常用API)》里面讲解了
六,函数
py中的函数写法有很多种,我觉得很多都不需要掌握,这里就不列举了。
这里主要讲py3.9版本的函数,这种可读性和维护性都比较强,也比较好理解,比如我写一个求和函数,首先函数一般使用def关键字进行定义,然后后面接上方法名字,括号里面是参数,参数后面加冒号用来定义参数类型,最后是->箭头表示返回值的类型
def add(a: int, b: int) -> int:
return a + b
print(add(1, 2))#3
或者没有返回值的:
def add(a: int,b: int):
print(a+b)
add(1, 2)#3
返回值是数组的:
#翻转列表的函数
def list_func(nums: list[int])->list[int]:
l, r=0, len(nums)-1
while(l<r):
nums[l], nums[r] = nums[r], nums[l]
l+=1
r-=1
return nums
my_list = [1,2,3,4,5]
print(list_func(my_list))#[5, 4, 3, 2, 1]
小结
一些常用的api,比如max,min这种,下一篇文章再讲。写文章的过程中还是觉得条理性没那么好,后面的循环和函数讲的也比较草率,我在写这部分的时候,感觉很多东西还是题目实战并且多练习才对,所以就没写很多,简单的把基础的介绍了一下。下一篇文章后就基本都是题目,思路和题解了,不想用py的也可以关注我,之后更新的题解我会用java,cpp,go都写一遍,一起进步享受编程解题的乐趣和快感
作者:多思考少编码