当前位置: 首页 > article >正文

数据结构与算法 —— 常用算法模版

数据结构与算法 —— 常用算法模版

  • 二分查找
  • 素数筛
  • 最大公约数与最小公倍数

二分查找

人间若有天堂,大马士革必在其中;天堂若在天空,大马士革必与之齐名。 —— 阿拉伯谚语
算法若有排序,二分查找必在其中;排序若要使用,二分查找必与之齐名。 —— 木子李

(1)初始化左右指针
left 指向数组的起始位置(索引0)。
right 指向数组的末尾位置(索引len(arr) - 1)。
(2)循环条件
while left <= right:只要左指针不大于右指针,就继续搜索。这意味着搜索区间是有效的。
计算中间位置:
mid = left + (right - left) // 2:这是计算中间位置的标准方式。使用 (right - left) // 2 而不是 (right + left) // 2 是为了防止当 left 和 right 都很大时,它们的和可能超过整数类型的最大值,导致溢出。通过先减去再除以2,可以安全地计算出中间索引。
(3)检查中间元素
如果 arr[mid] == target,则找到了目标元素,返回其索引 mid。
如果 arr[mid] < target,说明目标元素在 mid 的右侧,因此将 left 更新为 mid + 1,缩小搜索范围到右半部分。
如果 arr[mid] > target,说明目标元素在 mid 的左侧,因此将 right 更新为 mid - 1,缩小搜索范围到左半部分。
(4)返回结果
如果循环结束还没有找到目标元素,则返回 -1,表示目标元素不在数组中。
(5)注意事项
确保输入的数组 arr 是有序的,因为二分查找依赖于数组的有序性。
mid 的计算方式可以防止整数溢出,这是在处理大数据集时的一个重要考虑因素。
返回值 -1 表示未找到目标元素,可根据需要自定义这个返回值。

# 排序是为了更快查找,不为了更快查找没必要排序。
def binary_search(arr, target):
    left, right = 0, len(arr) - 1
    
    while left <= right:
    	# 防止(left + right)直接相加导致的整数溢出,这里mid有两种写法
        mid = left + (right - left) // 2  
        
        # 检查mid位置的元素
        if arr[mid] == target:
            return mid  # 找到目标,返回索引
        elif arr[mid] < target:
            left = mid + 1  # 目标在mid右侧
        else:
            right = mid - 1  # 目标在mid左侧
    
    return -1  # 未找到目标,返回-1
array = [1,2,3,4,5]
for left in range(0, len(array)):
	for right in range(left, len(array)):
	    
		if (right - left) % 2 == 0:
			print("奇数个元素:(",end="")
		else:
			print("偶数个元素:(",end="")
		for x in range(left, right + 1):
		    if x < right:
		        print(f"{x},",end="")
		    if x == right:
		        print(f"{x}",end="")
		print(")")
		# 关于mid的两种写法
		print(f"mid = (right + left) // 2 = ", (right + left) // 2)
		print(f"mid = (right + left + 1) // 2 = ", (right + left + 1) // 2)
		print("\n")

奇数个元素:(0)
(right + left) // 2 = 0
(right + left + 1) // 2 = 0

偶数个元素:(0,1)
(right + left) // 2 = 0
(right + left + 1) // 2 = 1

奇数个元素:(0,1,2)
(right + left) // 2 = 1
(right + left + 1) // 2 = 1
可以看到在偶数个元素时,(right + left) // 2 = mid下标偏左,(right + left + 1) // 2 = mid下标偏右,奇数个元素时都是对的

参考文章与视频链接
[1]《大马士革刀传奇,一把宝刀,两座刀锋下的城市》

素数筛

def sieve_of_eratosthenes(n):
    # 创建一个布尔数组,初始化为 True,表示所有数都是素数
    is_prime = [True] * (n + 1)
    p = 2
    
    while (p * p <= n):
        # 如果 is_prime[p] 没有被改变,那么它是一个素数
        if is_prime[p]:
            # 更新 p 的所有倍数为 False,表示它们不是素数
            for i in range(p * p, n + 1, p):
                is_prime[i] = False
        p += 1
    
    # 收集所有的素数
    prime_numbers = [p for p in range(2, n + 1) if is_prime[p]]
    return prime_numbers

# 示例使用
n = 30
primes = sieve_of_eratosthenes(n)
print(f"小于或等于 {n} 的素数有: {primes}")

最大公约数与最小公倍数

# 最大公约数
"""
a = 40, b = 104
算法过程
a       b   remain
40  % 104 =   40 
104 %  40 =   24
40  %  24 =   16
24  %  16 =   8
16  %   8 =   0
8   %   0 =   不执行,结束
return a
"""
def gcd(a: int, b: int):
    while b != 0:
        remain = a % b
        a = b
        b = remain
    return a


# 最小公倍数
def lcm(a: int, b: int):
    return int((a * b) / gcd(a, b))


if __name__ == '__main__':
    print(gcd(400, 20))  # 20
    print(lcm(400, 20))  # 400


http://www.kler.cn/a/527063.html

相关文章:

  • 洛谷 P10288 [GESP样题 八级] 区间 C++ 完整题解(STL二分法)
  • SpringCloudGateWay和Sentinel结合做黑白名单来源控制
  • 使用 OpenResty 构建高效的动态图片水印代理服务20250127
  • 随机矩阵投影长度保持引理及其证明
  • 网站快速收录:提高页面加载速度的重要性
  • AI时序预测: iTransformer算法代码深度解析
  • c++进制转换
  • 计算机网络部分知识点(王道考研笔记)
  • 第05章 15 VTK中Implicit Function的作用原理与基本应用场合
  • 本地部署DeepSeek开源多模态大模型Janus-Pro-7B实操
  • vue插件安装后使用没反应
  • 一文读懂 Faiss:开启高维向量高效检索的大门
  • TCP UDP Service Model
  • 玩转大语言模型——配置图数据库Neo4j(含apoc插件)并导入GraphRAG生成的知识图谱
  • Python练习(3)
  • 计算机网络 笔记 传输层
  • flowable expression和json字符串中的双引号内容
  • DeepSeek大模型技术深度解析:揭开Transformer架构的神秘面纱
  • 4-图像梯度计算
  • Java小白入门教程:两大类型的修饰符以及示例
  • Kafka常见问题之 java.io.IOException: Disk error when trying to write to log
  • 如何本地部署DeepSeek
  • 在Ubuntu子系统中基于Nginx部署Typecho
  • 实现B-树
  • 供应链系统设计-供应链中台系统设计(十四)- 清结算中心设计篇(三)
  • PHP实现混合加密方式,提高加密的安全性(代码解密)