备战蓝桥杯大赛:Python必刷题单之基础算法

字符串

题目链接

字符串编辑

s = input()
a = list(map(str, input().split()))
if a[0] == 'D':
    # 将第一个出现的字符替换为空字符
    # 注意,replace方法不会改变原字符串的内容
    s = s.replace(a[1], "", 1)
elif a[0] == 'I':
    index = s.rfind(a[1])
    # 将字符串转为列表,进行插入操作
    b = list(s)
    b.insert(index, a[2])
    # 将列表连接为字符串
    s = "".join(b) 
else:
    s = s.replace(a[1], a[2])
print(s)

枚举

百钱买百鸡

题目链接

# 枚举公鸡 21次
for x in range(0, 21):
    # 枚举母鸡 34
    for y in range(0, 34):
        # 枚举小鸡
        z = 100 - x - y
        # 找到符合条件的解
        if 5 * x + 3 * y + z // 3 == 100 and z % 3 == 0:
            print(x, y, z)

胡萝卜

题目链接

n = int(input())
ans = 0
for i in range(1, n): # 灰兔
  for j in range(i, n): # 白兔
    k = n - i - j # 黑兔
    if k > 0 and k >= j:
      ans += 1
print(ans)

数组查找及替换

题目链接

n, b = map(int, input().split())
a = list(map(int, input().split()))
a.sort()
for x in a:
  if x % b == 0:
    continue
  if x >= ord('A') and x <= ord('Z'):
    print(chr(x), end = " ")
  else:
    print(x, end = " ")

校门外的树

题目链接

n, m = map(int, input().split())
a = [0] * (n + 1)
for i in range(m):
    L, R = map(int, input().split())
    for j in range(L, R + 1):
        a[j] = 1
ans = 0
for i in range(n + 1):
    if a[i] == 0:
        ans += 1
print(ans)

铺地毯

题目链接

n = int(input())
a = []
for i in range(n):
    x, y, g, k = map(int, input().split())
    a.append([x, y, x + g, y + k])
x, y = map(int, input().split())
ans = -1
# 从后向前遍历地毯
i = n - 1
while i >= 0:
    if x >= a[i][0] and x <= a[i][2] and y >= a[i][1] and y <= a[i][3]:
        ans = i + 1
        break
    i -= 1
print(ans)

回文日期

题目链接

a = {1:31, 2:28, 3:31, 4:30, 5:31, 6:30, 7:31, 8:31, 9:30, 10:31, 11:30, 12:31}
# 将年份翻转组合成回文日期
def reverse(n):
    date = n
    for i in range(4):
        date = date * 10 + n % 10
        n //= 10
    return date
# 检查年月日是否合法
def check(date):
    year = date // 10000
    if year % 400 == 0 or year % 4 == 0 and year % 100 != 0:
        a[2] = 29
    else:
        a[2] = 28
    month = date // 100 % 100;
    if month == 0 or month > 12:
        return False
    day = date % 100
    if day == 0 or day > a[month]:
        return False
    return True
    
start = int(input())
end = int(input())
ans = 0
# 枚举所有年份
for i in range(0, 10000):
    date = reverse(i)
    if date >= start and date <= end: 
        if check(date):
            ans += 1
print(ans) 

排序

区间k大数查询

题目链接

n = int(input())
a = list(map(int, input().split()))
m = int(input())
for i in range(m):
    L, R, k = map(int, input().split())
    b = a[L - 1:R]
    b.sort(reverse = True)
    print(b[k - 1])

桶排序—明明的随机数

题目链接

n = int(input())
a = list(map(int, input().split()))
cnt = [0] * 1010
ans = 0
for x in a:
    if cnt[x] == 0:
        ans += 1
    cnt[x] += 1
print(ans)
for i in range(1, 1001):
    if cnt[i] != 0:
        print(i, end = " ")

多关键字排序 - 奖学金

题目链接

n = int(input())
a = []
for i in range(n):
    c, m, e = map(int, input().split())
    a.append((i + 1, c, m, e, c + m + e))
# 按照总分和语文成绩从高到低排序
a.sort(key = lambda x : (x[4], x[1]), reverse = True)
for i in range(5):
    print(a[i][0], a[i][4])

贪心

排队接水

题目链接

n = int(input())
b = list(map(int, input().split()))
a = []
for i in range(1, n + 1):
    a.append((i, b[i - 1]))
# 按照打水时间从小到大排序
a.sort(key = lambda x : x[1])
for x in a:
    print(x[0], end = ' ')
# 计算总的等待时间
ans = 0
for i in range(1, n + 1):
    ans += a[i - 1][1] * (n - i)

print("\n%.2f" % (ans / n))

线段覆盖

题目链接
数据量比较大,会TLE。

n = int(input())
a = []
for i in range(n):
    a.append(list(map(int, input().split())))
a.sort(key = lambda x : x[1])
last = -1
ans = 0
for x in a:
    # 当前会议的开始时间不早于上个会议的结束时间
    if x[0] >= last:
        ans += 1
        last = x[1]
print(ans)

哈夫曼树 - 合并果子

题目链接

import heapq
heap = []
n = int(input())
a = list(map(int, input().split()))
# 构建小顶堆
for x in a:
    heapq.heappush(heap, x)
ans = 0
while len(heap) > 1:
    a = heapq.heappop(heap)
    b = heapq.heappop(heap)
    ans += a + b;
    heapq.heappush(heap, a + b)
print(ans)

和最大子序列

题目链接

n = int(input())
a = list(map(int, input().split()))
ans = -1e9
sum = 0
for x in a:
    if sum < 0:
        sum = x
    else:
        sum += x
    ans = max(ans, sum)
print(ans)

二分查找

二分查找 - 数的范围

题目链接

def lower_bound(L, R, k):
    while L < R:
        mid = (L + R) // 2
        if a[mid] >= k:
            R = mid
        else:
            L = mid + 1
    if a[L] == k:
        return L
    else:
        return -1
def upper_bound(L, R, k):
    while L < R:
        mid = (L + R + 1) // 2
        if a[mid] <= k:
            L = mid
        else:
            R = mid - 1
    if a[L] == k:
        return L
    else:
        return  -1
n, m = map(int, input().split())
a = list(map(int, input().split()))
while m != 0:
    m -= 1
    k = int(input())
    L = lower_bound(0, n - 1, k)
    R = upper_bound(0, n - 1, k)
    print(L, R)

二分答案 - 砍树

题目链接

n, m = map(int, input().split())
a = list(map(int, input().split()))
L, R = 0, max(a)
# 检查高度h是否满足条件
def check(h):
    ans = 0
    for x in a:
        if x >= h:
            ans += x - h
    return ans >= m
# 二分满足条件的最大高度
while L < R:
    mid = (L + R + 1) // 2
    if check(mid):
        L = mid
    else:
        R = mid - 1

print(L)

    

前缀和

前缀和

题目链接

n, m = map(int, input().split())
a = list(map(int, input().split()))
s = {0:0}
for i in range(1, n + 1):
    s[i] = s[i - 1] + a[i - 1]
for i in range(m):
  L, R = map(int, input().split())
  print(s[R] - s[L - 1])

二维前缀和 - 领地选择

题目链接

有一个测试样例TLE

n, m, c = map(int, input().split())
# 初始化二维列表
a = [[0] * (m + 1) for _ in range(n + 1)]
# 输入数据,下标从1开始
for i in range(n):
    b = (list(map(int, input().split())))
    for j in range(m):
        a[i + 1][j + 1] = b[j]
# 构造前缀和数组  
for i in range(1, n + 1):
    for j in range(1, m + 1):
        a[i][j] += a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1]

ans = -1e9
x = y = 1
for i in range(1, n - c + 1):
    for j in range(1, m - c + 1):
        x1, y1 = i, j
        x2, y2 = i + c - 1, j + c - 1
        s = a[x2][y2] - a[x1 - 1][y2] - a[x2][y1 - 1] + a[x1 - 1][y1 - 1]
        if s > ans:
            ans = s
            x = x1
            y = y1
print(x, y)

差分 - 植树节

题目链接

m = int(input())
# 差分数组初始化
d = [0] * 1000010
R = 0 # 右边边界
for i in range(m):
    a, b = map(int, input().split())
    d[a] += 1
    d[b + 1] -= 1
    R = max(R, b)
ans = d[0]
for i in range(1, R + 1):
    d[i] += d[i - 1]
    ans = max(ans, d[i])
print(ans)

数学知识

完数

题目链接

n = int(input())
sum = 0
a = 1
# 这里需要每次求出一对约束,优化后,时间复杂度为O(sqrt(n))
while a * a <= n:
    if n % a == 0:
        sum += a
        b = n // a
        if b != n and b != a:
            sum += b
    a += 1
# 注意:特殊处理n为1的情况
if n == 1 or sum != n:
    print("no")
else:
    print("yes")
```python

## 分解质因数
[题目链接](http://oj.yogeek.cn/problem/lq_cup1058)
```python
# 质数判断
def is_prime(n):
    i = 2
    while i * i <= n:
        if n % i == 0:
            return 0
        i += 1
    else:
        return 1

a, b = map(int, input().split())

for n in range(a, b + 1):
	# 如果n为质数,直接输出,否则会TLE
    if is_prime(n):
        print("%d=%d" % (n, n))
        continue
    #质因数分解
    p = 2
    print("%d=" % n, end = "")
    while n > 1:
        while n % p == 0:
            print(p, end = "")
            n //= p
            if n > 1:
                print("*", end = "")
            else:
                print("")
        p = p + 1

筛质数

题目链接

# 获取不超过n的所有质数
def get_primes(n):
  # 遍历2到n的所有数
  for i in range(2, n + 1):
      # 如果该数没有被筛除
      if st[i] == 0:
        # 添加到质数列表中
        p.append(i)
        # 将i的倍数筛除
        j = 2 * i
        while j <= n:
            st[j] = 1
       	    j = j + i
  # 返回质数个数
  return len(p)
p = []
n = int(input())
# 标记数组,没有筛除时状态为0
st = [0] * (n + 10)
print(get_primes(n))

回溯算法

阮小二买彩票

题目链接

s = input()
# 将s转为int列表
s = [int(x) for x in s]
n = len(s)
a = []
ans = []
st = [0] * 10

def dfs(t):
    # 找到一组序列后,将其转为字符串加入ans列表
    if t == n:
        ans.append("".join([str(x) for x in a]))
        return
    for i in range(0, n):
        if st[i] == 0:
            a.append(s[i])
            st[i] = 1
            dfs(t + 1)
            a.pop()
            st[i] = 0
# 回溯生成所有序列
dfs(0)
# 将得到的序列进行排序
ans.sort()
for i in range(len(ans)):
    if i == 0:
        print(ans[i])
    # 如果跟上一个序列不同则输出
    elif ans[i] != ans[i - 1]:
        print(ans[i])

八皇后问题

题目链接

a = [0] * 20
c = [0] * 20
u = [0] * 20
v = [0] * 20
ans = []
n = 8
def dfs(t):
    global n
    if t == n:
        b = [str(a[i]) for i in range(n)]
        ans.append("".join(b))
        return
    for i in range(n):
        if c[i] == 1 or u[i + t] == 1 or v[i - t + n] == 1:
            continue
        c[i] = u[i + t] = v[i - t + n] = 1
        a[t] = i + 1
        dfs(t + 1)
        c[i] = u[i + t] = v[i - t + n] = 0

dfs(0)      
m = int(input())
while m > 0:
    n = int(input())
    print(ans[n - 1])
    m -= 1

黑白皇后问题

题目链接

# 输入
g = []
n = int(input())
ans = 0
for i in range(n):
    g.append(list(map(int, input().split())))

# 初始化黑白皇后的列、对角线状态
cw = [0] * (n + 10)
uw = [0] * (n * 3)
vw = [0] * (n * 3)
cb = [0] * (n + 10)
ub = [0] * (n * 3)
vb = [0] * (n * 3)
# 搜索白皇后的情况
def dfs_w(t):
    global n
    if t == n:
    	# 成功放置n个白皇后,再搜索黑皇后的情况
        dfs_b(0)
        return
    for i in range(n):
        if cw[i] == 1 or uw[i + t] == 1 or vw[i - t + n] == 1:
            continue;
        if g[t][i] == 0:
            continue;
        g[t][i] = 0
        cw[i] = uw[i + t] = vw[i - t + n] = 1
        dfs_w(t + 1)
        g[t][i] = 1
        cw[i] = uw[i + t] = vw[i - t + n] = 0
# 搜索黑皇后的情况
def dfs_b(t):
    global ans
    global n
    if t == n:
    	# 成功放置后,方案总数加1
        ans += 1
        return
    for i in range(n):
        if cb[i] == 1 or ub[i + t] == 1 or vb[i - t + n] == 1:
            continue;
        if g[t][i] == 0:
            continue;
        cb[i] = ub[i + t] = vb[i - t + n] = 1
        dfs_b(t + 1)
        cb[i] = ub[i + t] = vb[i - t + n] = 0
# 搜索白皇后的情况
dfs_w(0)
print(ans)

递推

N阶楼梯上楼问题

题目链接

n = int(input())
f = [0] * (n + 10)
f[1] = 1
f[2] = 2
for i in range(3, n + 1):
  f[i] = f[i - 1] + f[i - 2]
print(f[n])

杨辉三角形

题目链接

n = int(input())
f = []
# 初始化n行杨辉三角
for i in range(n):
    f.append([0] * (i + 1))
print(f)
# 计算杨辉三角
i = 0
while i < n:
    j = 0
    while j <= i:        
        if(j == 0 or j == i):
            f[i][j] = 1
        else:
            f[i][j] = f[i - 1][j] + f[i - 1][j - 1]
        j += 1
    i += 1
# 输出杨辉三角
i = 0
while i < n:
    j = 0
    while j <= i:
        print(f[i][j], end = " ")
        j += 1
    print("")
    i += 1

错排问题

题目链接
递推算法题解:错排问题

n = int(input())
f = {}
f[1] = 0
f[2] = 1
for i in range(3, n + 1):
    f[i] = (f[i - 1] + f[i - 2]) * (i - 1) % 100003
print(f[n])

动态规划

坐标型动态规划——夺宝奇兵

题目链接

n = int(input())
f = []
for i in range(n):
    f.append(list(map(int, input().split())))
# 从山底向上枚举计算
i = n - 2
while i >= 0:
    j = 0
    while j <= i:
        f[i][j] += max(f[i + 1][j], f[i + 1][j + 1])
        j += 1
    i -= 1
print(f[0][0])
  • 7
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少儿编程乔老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值