算法通识
有太多的天才程序员、知名学者、行业大佬,都或多或少写过算法相关的书籍。目前算法已经是每个程序员必备的技能之一,是进入大厂的第一道门槛。
本文面向初学者,由浅入深的给出一些算法题解,帮助你理解算法的基本概念和实现方式。
tip
基础
大O表示法是一种表示算法时间复杂度的方法。它表示算法运行时间与输入规模之间的关系。
O(1) # 常数时间复杂度
O(log n) # 对 数时间复杂度
O(n) # 线性时间复杂度
O(n log n) # 线性对数时间复杂度
O(n^2) # 平方时间复杂度
对于大O表示法,我们只需要关注最高次项并忽略系数。例如O(2n + 1)可以简化为O(n)。
请你完成下面的练习并给出其时间复杂度。
二分查找
描述
给定一个有序列表和一个目标值,请你查找目标值在列表中的索引。如果目标值不存在,则返回-1。
arr = [1, 2, 6, 7, 8, 9, 10]
target = 6
输出: 2
arr = [1, 2, 6, 7, 8, 9, 10]
target = 0
输出: -1
题解
def binary_search(arr, target):
left, right = 0, len(arr) - 1
while left <= right:
mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1
print(binary_search([1, 2, 6, 7, 8, 9, 10], 0))# -1
print(binary_search([1, 2, 6, 7, 8, 9, 10], 6))# 2
冒泡排序
描述
给定一个列表,请你对列表的元素进行排序。
示例:
输入: [13, 22, 6, 99, 11, 0]
输出: [0, 6, 11, 13, 22, 99]
输入: [13, 22, 6, 99, 11, 0]
输出: [0, 6, 11, 13, 22, 99]
题解
list1 = [13, 22, 6, 99, 11, 0]
for a in range(len(list1)):
for b in range(a,len(list1)):
if list1[a] < list1[b]: #如果m大于了n
list1[a] ,list1[b] = list1[b],list1[a]#交换位置
print(list1)
分 治
分治法是一种将问题分解为更小的子问题,然后解决子问题,最后合并子问题结果的算法。
快速排序
描述
快速排序(Quicksort)是对冒泡排序的一种改进算法。
该算法的实现基本可分为以下几步:
在数组中选一个基准数(通常为数组第一个)。 将数组中小于基准数的数据移到基准数左边,大于基准数的移到右边 对于基准数左、右两边的数组,不断重复以上两个过程,直到每个子集只有一个元素,即为全部有序。
请你编写它的实现代码。
题解
def quick_sort(arr):
"""
快速排序
:param arr: 待排序的List
:return: 排序后的List
"""
# 递归结束条件:如果列表长度小于等于1,直接返回
if len(arr) <= 1:
return arr
# 创建左右2个空列表
left = []
right = []
# 选择一个选中值(pivot),选择第一个元素
pivot = arr[0]
# 将元素分配到左右列表
for i in range(1, len(arr)):
if arr[i] <= pivot: # 小于等于pivot的元素放入左列表
left.append(arr[i])
else: # 大于pivot的元素放入右列表
right.append(arr[i])
# 递归排序左右两部分,并合并结果
return quick_sort(left) + [pivot] + quick_sort(right)
# 测试数据
if __name__ == '__main__':
arr = [17, 56, 71, 38, 61, 62, 48, 28, 57, 42, 10, 21, 12, 90] # 长度为14
sorted_arr = quick_sort(arr)
print("快速排序结果:", sorted_arr)
密码组合
描述
Python中的string模块包含了许多字符,请根据以下提示设计一个函数:
参数1:密码可用字符的列表 参数2:密码的长度 输出:一个符合要求的所有的密码组合
题解
def set_password(chars, length):
passwords = []
def get_password(char, length):
if len(char) == length: # 修复:检查当前密码长度,而不是字符集长度
passwords.append(char) # 修复:添加当前构建的密码,而不是字符集
return
for i in chars:
get_password(char + i, length)
get_password("", length)
return passwords
print(set_password(['a', 'b', 'c'], 2))# ['aa', 'ab', 'ac', 'ba', 'bb', 'bc', 'ca', 'cb', 'cc']
print(set_password(['a', 'b', 'c'], 3))# ['aaa', 'aab', 'aac', 'aba', 'abb', 'abc', 'aca', 'acb', 'acc', 'baa', 'bab', 'bac', 'bba', 'bbb', 'bbc', 'bca', 'bcb', 'bcc', 'caa', 'cab', 'cac', 'cba', 'cbb', 'cbc', 'cca', 'ccb', 'ccc']
括号组合
描述
给定一个数字n,请你生成所有可能的括号组合
题解
def generate_parenthesis(n):
def backtrack(s, left, right):
if len(s) == 2 * n:
result.append(s)
return
if left < n:
backtrack(s + '(', left + 1, right)
if right < left:
backtrack(s + ')', left, right + 1)
result = []
backtrack('', 0, 0)
return result
print(generate_parenthesis(3))# ['((()))', '(()())', '(())()', '()(())', '()()()']
质数分解
描述
每个数字可以写成多个质数的乘积,给定一个数字,请你分解为多个质数
题解
def fun(num, list=None):
if list is None:
list = []
for i in range(2, num):
while num % i == 0:
list.append(i)
num = int(num / i)
if num > 1:
fun(num)
return list
x = 9*5
print(fun(x))# [3, 3, 5]