def quick_sort(l,r,data):
if l >= r:
return
i = l - 1 # 左端指针
j = r + 1 # 右端指针
pivot = data[(i+j) // 2] #中间值,随意取;但是一般选择中间值
while i < j:
while 1:
i += 1 # 左边指针向右移
if data[i] >= pivot: #找到不小于privot的然后break
break
while 1: # 右边指针向左移
j -= 1
if data[j] <= pivot: # 找到不大于privot的然后break
break
if i < j:
data[i],data[j] = data[j],data[i] # 如果此时i小于j,则交换
quick_sort(l,j,data) #对左边子区间进行排序
quick_sort(j+1,r,data) #对右半子区间进行排序
def main():
l = 0
r = n-1
quick_sort(l,r,data)
if name == “__main__”:
n = int(input()) #输入数组长度
data = [int(x) for x in input().split()] #输入数组
main()
print(’ '.join(list(map(str, data))))
###### 找到第k个数:
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=%2FUsers%2Fmac%2FDocuments%2F%E5%AD%A6%E4%B9%A0%2Fpython%2FAlgorithm%2FAcwing_start%2Fimage-20240326203252589.png&pos_id=img-3CUM7bPJ-1711731100738)
答案:
n, k = map(int,input().split())
nums = list(map(int,input().split()))
def quick_sort(nums):
if (len(nums) <= 1): return nums;
privot = nums[len(nums) // 2]
left = [x for x in nums if x < privot]
mid = [x for x in nums if x == privot]
right = [x for x in nums if x > privot]
return quick_sort(left) + mid + quick_sort(right)
if name == “__main__”:
nums = quick_sort(nums)
print(nums[k -1])
#### 归并排序
区别于快排:快排的分界值可以是任意的
但是归并排序是**下标的中间值**
##### 核心:
一个是将数组一分为二,一个无序的数组成为两个数组.
另外一个操作就是,合二为一,将两个有序数组合并成为一个有序数组.
##### 方法:
1. 先一分为二
2. 递归排序
3. 归并,将左右两个有序序列合并为一个序列
def merge_sort(data, l, r): # 数组的两个边界是l\r
if l >= r:
return
mid = (l + r) // 2 # 划分数据
merge_sort(data, l, mid)
merge_sort(data, mid + 1, r)
tmp = [] # 创建一个临时列表
i = l
j = mid + 1
while (i <= mid) and (j <= r): # 两指针i/j向中间移动,比较数值,添加到tmp中
if data[i] <= data[j]:
tmp.append(data[i])
i += 1
else:
tmp.append(data[j])
j += 1
# 两数组合并
tmp += data[i:mid + 1] # 将左侧分区的所有元素添加到tmp列表中
tmp += data[j:r + 1] # 将右侧分区的所有元素添加到tmp列表中
data[l:r + 1] = tmp # tmp替换原来的data
if name == “__main__”:
n = int(input())
data = list(map(int,input().split()))
merge_sort(data, l, r)
print(merge_sort(0,n-1))
###### 逆序队数量:
![image-20240326221203414](https://img-blog.csdnimg.cn/img_convert/327bad8a00e0aade11a84b015831e93b.png)
##### 三类:
1. 逆序对都在左半边
2. 逆序对都在右半边
3. 逆序对都在两边都有
![image-20240326221727215](https://img-blog.csdnimg.cn/img_convert/f5794fbcb32203237b9f34c5b546d87d.png)
def merge_sort(l,r):
if l >= r:
return 0
mid = (l + r) // 2
i = l
j = mid + 1
tmp = []
num = merge_sort(l,mid) + merge_sort(mid+1,r)
while i <= mid and j <= r:
if data[i] <= data[j]:
tmp.append(data[i])
i += 1
else:
tmp.append(data[j])
j += 1
num += mid - i + 1 # 如果不满足,那么第一个数组中剩余的所有数,都会和它构成逆序对
tmp.extend(data[i:mid+1])
tmp.extend(data[j:r+1])
data[l:r+1] = tmp
return num
if name == “__main__”:
n = int(input())
data = list(map(int,input().split()))
print(merge_sort(0,n-1))
#### 二分
* ##### 整数二分:
有单调性一定可以二分,可以二分的题不一定二分
找到某个性质,可以将区间一分为二,二分可以寻找边界
1. 二分前,先将搜索范围分为两个部分并定义check函数以检验是否满足其中一个区间的性质
2. l和r的范围内一定包含了最终的边界点
3. 此模板更像是边界二分法
右边界:True: [mid,r];False:[l,mid-1]
左边界:True:[l,mid];False:[mid+1,r]
4. **为什么寻找右边界(x⩽c)时,mid = (l+r+1) // 2,而寻找左边界(x⩾c)时,mid = (l+r) // 2**
因为寻找右边界…],需要不断往后移动,所以必须得向后多一位
因为寻找左边界[…,需要不断迁移,所以必须向前多一位
* 注意⚠️:所谓的二分算法,就是我们**知道当前的候选区间**中,一定存在我们要找到的答案,而且我们发现这个区间拥有**单调性质**此类的性质,那么我们可以**不停地缩减候选区间的范围**,达到排除无用答案的效果.
###### 数的范围:
![image-20240328165614324](https://img-blog.csdnimg.cn/img_convert/fd58e62fb6aa0473d4013f1b8631b9fb.png)
n,m=map(int,input().split())
data=list(map(int,input().split()))
def dichotomous(data,n,m):
while m:
target=int(input())
l=0
r=n-1
# 先寻找左边界,即>=target的分界点
while l<r:
mid=(l+r)//2 # 左边界
if data[mid]>=target:
r=mid
else:
l=mid+1
if data[l]!=target:
print(“-1-1”)
else:
print(l,end=" ")
l=0
r=n-1
# 寻找右边界,即<=target的分界点
while l<r:
mid=(l+r+1)//2 # 右边界
if data[mid]<=target:
l=mid
else:
r=mid-1
print(l)
if name == “__main__”:
for k in range(m):
dichotomous(data,n,m)
###### 数的三次方根
![image-20240328204002666](https://img-blog.csdnimg.cn/img_convert/1b14e2eaac487e58d8ca53a72981c833.png)
给定一个浮点数n,求它的三次方根
方法一 :没有用到二分法
def cubic_root(n):
if n>=0:
return “{:.6f}”.format(n ** (1/3))
else:
n = -n
root=format(n ** (1/3))
return “{:.6f}”.format(-float(root))
if name== ‘__main__’:
n = float(input())
print(cubic_root(n))
* ##### 浮点二分
除了上面有提到的整数二分法,这个题就是很典型的浮点数二分
⏰**整数二分和浮点数二分的区别:**
唯一区别是浮点数没有整除, 区间长度可以严格的缩小一半
>
> l=mid;
>
>
> r=mid;
>
>
>
过程:
1. 首先输入x在区间-10000~10000
2. 寻找p点(也就是x的三次方根)
3. 二分找边界值
if name == ‘__main__’:
n = float(input())
st = 0 # 标记位,用来标记n是否是负数
if n < 0:
st = 1
n = -n
l, r = 0, 100
while ((r - l) > 1e-8):
mid = (l + r) / 2.0
if (mid**3 >= n):
r = mid # 边界移动
else:
l = mid
if st:
l = -l
print(“{:.6f}”.format(l)) # 保留6位小数
#### 高精度
注意⚠️:其实python自带高精度哈哈哈!
print(int(input())-int(input()))
print(int(input())+int(input()))
print(int(input())*int(input()))
print(int(input())/int(input()))
这样输出也是高精度
##### 高精度加法
**思路:**
模拟手动加法计算
>
> 例如计算:567 + 28
>
>
> 1. 先个位相加: 7 + 8 = 15,所以结果的个位是5,向十位进 1
> 2. 再十位相加: 6 + 2 + 1(进位)= 9, 所以十位是 9,向百位进 0
> 3. 再百位相加: 5 + 0 = 5, 所以结果的百位是 5
> 4. 综上,计算结果为 595
>
>
>
**算法**:
>
> 计算 567 + 28
>
>
> 1. 用 a, b 两个字符串存储输入。a = 567, b = 28
> 2. 为了方便计算,将两个数分别 倒序 存放在 A, B 两个整数数组中。 A = [7, 6, 5], B = [8, 2]
> 3. 新建整数数组 C 保存结果,整型变量 t 保存进位,初始 t = 0.
> 4. 将各个位上的数字相加,求出结果对应位上的数字和进位。
>
> 例如对个位计算: A[0] + B[0] = 7 + 8 = 15, 结果个位上是 5, 进位是 1. 所以 C[0] = 5, 进位 t = 1
> 5. 最后把结果数组 C 中就保存了计算倒序结果,倒序输出就是答案
>
>
>
**模版:**
高精度加法
a=list(input())
b=list(input())
def add(a,b):
a.reverse() # 倒叙相加嘛
b.reverse()
c = [0]*max(len(a),len(b)+1) # 生成一个长度为a和b中最长的数+1的数组
for i in range(len(a)):
c[i] = int(a[i])
for i in range(len(b)):
c[i] += int(b[i])
for i in range(len©-1):
if c[i] >= 10: # 如果c[i]大于10,则进位
c[i] -= 10
c[i+1] += 1
while len© > 1 and c[-1] == 0:
c.pop() # 如果最后一位是0,则删除(也就是最高位)
c.reverse()
combined = int(‘’.join(map(str, c))) # 将数组转化为字符串,再转化为整数
print(combined)
if name == ‘__main__’:
add(a,b)
##### 高精度减法
**思路:**
1. 减法的借位处理
2. 相减为负数处理
3. 高位为0处理
**模版:**
def subtract(a, b):
a.reverse()
b.reverse()
c = [0]*max(len(a),len(b)+1)
for i in range(len(a)):
c[i] = int(a[i])
for i in range(len(b)):
c[i] -= int(b[i])
for i in range(len©-1):
if c[i] < 0:
c[i] += 10
c[i+1] -= 1
while len© > 1 and c[-1] == 0:
c.pop()
c.reverse()
if c[0] == 0 and len© > 1:
c[0] = ‘-’
combined = ‘’.join(map(str, c))
else:
combined = int(‘’.join(map(str, c)))
return combined
if name == ‘__main__’:
a = list(input())
b = list(input())
combined2 = ‘’.join(map(str, a))
combined3 = ‘’.join(map(str, b))
if int(combined2) < int(combined3): #判断a和b的大小,如果a<b,则输出负数
num=0-subtract(b, a)
print(num)
else:
num=subtract(a, b)
print(num)
##### 高精度乘法
**思路:**
1. a/b循环相乘
2. 注意进位
3. 注意高位为0处理
**模版:**
def multiply(a, b):
a.reverse()
b.reverse()
c = [0]*(len(a)+len(b))
for i in range(len(a)): # 循环a
for j in range(len(b)): # 循环b
c[i+j] += int(a[i]) * int(b[j])
for i in range(len©-1):
c[i+1] += c[i] // 10 # 除以10的进位,这样直接取整就是进位,不用和10比较
c[i] %= 10 # 取余
while len© > 1 and c[-1] == 0:
c.pop()
c.reverse()
return ‘’.join(map(str, c))
if name == ‘__main__’:
a = list(input())
b = list(input())
print(multiply(a, b))
##### 高精度除法
**思路:**
1. a变为数组,b不变
2. 不需要倒置
3. 余数需要注意
4. 高位处理
**模版:**
def divide(a, b):
r = 0 # 余数
res = []
for i in range(len(a)):
r = r * 10 + int(a[i])
res.append(str(r // b)) # 商
r = r % b # 余数
while len(res) > 1 and res[0] == ‘0’:
res.pop(0)
return ‘’.join(res)
if name == ‘__main__’:
a = list(input())
b = int(input())
print(divide(a, b))
#### 前缀与差分
##### 前缀和:
什么是前缀和
原数组: a[1], a[2], a[3], a[4], a[5], …, a[n]
前缀和 Si为数组的前 i项和
前缀和: S[i] = a[1] + a[2] + a[3] + … + a[i]
注意: 前缀和的下标一定要从 1开始, 避免进行下标的转换
>
> s[0] = 0
> s[1] = a[1]
> s[2] = a[1] + a[2]
>
>
>
![image-20240329161207527](https://img-blog.csdnimg.cn/img_convert/0b65574b128675c3722f3622a529a143.png)
**作用:**
快速求出元素组中某段的和
###### 一维例题:
![image-20240329152010787](https://img-blog.csdnimg.cn/img_convert/b412196fb54d3ed3921996ef7d29f3c4.png)
**模版:**
n,m=map(int,input().split())
a=list(map(int,input().split()))
计算前缀和
prefix_sum = [0]*(n+1)
for i in range(1, n+1):
prefix_sum[i] = prefix_sum[i-1] + a[i-1]
def query(l, r):
return prefix_sum[r] - prefix_sum[l-1] # 返回区间和
if name == ‘__main__’:
for _ in range(m): # 这里_表示一个临时变量,不会被使用
l,r=map(int,input().split())
print(query(l,r))
###### 二维例题:
![image-20240329161512632](https://img-blog.csdnimg.cn/img_convert/38853acefb0dfc01dc9aa636e5026ab2.png)
**思路:**
1. S
[
i
,
j
]
S[i, j]
S[i,j] 即为图1红框中所有数的的和为:
S
[
i
,
j
]
=
S
[
i
,
j
−
1
]
+
S
[
i
−
1
,
j
]
−
S
[
i
−
1
,
j
−
1
]
+
a
[
i
,
j
]
S[i, j]=S[i, j-1]+S[i-1, j]-S[i-1, j-1]+a[i, j]
S[i,j]=S[i,j−1]+S[i−1,j]−S[i−1,j−1]+a[i,j]
2. (
x
1
,
y
1
)
,
(
x
2
,
y
2
**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**
**深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
**因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
![img](https://img-blog.csdnimg.cn/img_convert/4e13e5b9e65485d196e9a575ffc9a5ed.png)
![img](https://img-blog.csdnimg.cn/img_convert/da7fb42162b62ba680743df124c2d767.png)
![img](https://img-blog.csdnimg.cn/img_convert/46506ae54be168b93cf63939786134ca.png)
![img](https://img-blog.csdnimg.cn/img_convert/252731a671c1fb70aad5355a2c5eeff0.png)
![img](https://img-blog.csdnimg.cn/img_convert/6c361282296f86381401c05e862fe4e9.png)
![img](https://img-blog.csdnimg.cn/img_convert/9f49b566129f47b8a67243c1008edf79.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!**
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**
**如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)**
厂,18年进入阿里一直到现在。**
**深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
**因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
[外链图片转存中...(img-1iP2LP7v-1712671495939)]
[外链图片转存中...(img-R7d5GxAN-1712671495940)]
![img](https://img-blog.csdnimg.cn/img_convert/46506ae54be168b93cf63939786134ca.png)
![img](https://img-blog.csdnimg.cn/img_convert/252731a671c1fb70aad5355a2c5eeff0.png)
![img](https://img-blog.csdnimg.cn/img_convert/6c361282296f86381401c05e862fe4e9.png)
![img](https://img-blog.csdnimg.cn/img_convert/9f49b566129f47b8a67243c1008edf79.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!**
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**
**如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)**
<img src="https://img-community.csdnimg.cn/images/fd6ebf0d450a4dbea7428752dc7ffd34.jpg" alt="img" style="zoom:50%;" />