目 录CONTENT

文章目录

Python-基础场景题算法模板

~梓
2025-04-09 / 0 评论 / 0 点赞 / 24 阅读 / 0 字
温馨提示:
部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

一、生成字符串所有不同子串

例题一:

一个字符串的非空子串是指字符串中长度至少为 1 的连续的一段字符组成 的串。例如,字符串aaab 有非空子串a, b, aa, ab, aaa, aab, aaab,一共 7 个。 注意在计算时,只算本质不同的串的个数。 请问,字符串0100110001010001 有多少个不同的非空子串?

s = '0100110001010001'
subs = []

for i in range(len(s)+1):
    for j in range(i+1, len(s)+1):
        if(s[i:j] not in subs):
            subs.append(s[i:j])
print(len(subs))

优化方法:可以使用集合(set)来替代列表存储子串,因为集合的查找操作时间复杂度为 O(1)

s = '0100110001010001'
subs = set()

for i in range(len(s)+1):
    for j in range(i+1, len(s)+1):
        subs.add(s[i:j])

print(len(subs))

二、求列表中位数

中位数是将一组数据按照从小到大(或从大到小)的顺序排列,如果数据的个数是奇数,则处于中间位置的数为这组数据的中位数;如果数据的个数是偶数,则中间两个数据的平均数为这组数据的中位数。

例题一:

一家商店记录了连续 12 个月的销售额(单位:万元),数据为 [23, 25, 21, 27, 24, 26, 22, 28, 20, 29, 30, 19]。商店经理想要了解销售额的中间水平,以便制定合理的销售目标,帮助经理计算出这 12 个月销售额的中位数。

def find_median(lst):
    sorted_lst = sorted(lst)
    n = len(sorted_lst)
    if n % 2 == 1:
        return sorted_lst[n // 2]
    else:
        return (sorted_lst[n // 2 - 1] + sorted_lst[n // 2]) / 2


sales = [23, 25, 21, 27, 24, 26, 22, 28, 20, 29, 30, 19]
median = find_median(sales)
print(f"这12个月销售额的中位数是: {median} 万元")

三、斐波那契数列

斐波那契数列是指这样一个数列:0、1、1、2、3、5、8、13、21、34、……

def fibonacci_recursive(n):
    if n <= 1:
        return n
    return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2)


# 示例用法
n = 10
print(f"斐波那契数列的第 {n} 项是: {fibonacci_recursive(n)}")

例题一:

给定数列 1, 1, 1, 3, 5, 9, 17, …,从第 4 项开始,每项都是前 3 项的和。求 第 20190324 项的最后 4 位数字。

def find_last_four(n):
    if n <= 2:
        return 1
    a, b, c = 1, 1, 1
    for _ in range(3, n):
        # 每一步只保留结果的后四位
        a, b, c = b, c, (a + b + c) % 10000
    return c


num = 20190324
print(find_last_four(num))

四、整数拆分

将一个给定的整数拆分成若干个满足特定条件的整数之和,需要找出所有可能的拆分方式或计算拆分方式的数量。

例题一:

将 2019 拆分成 3 个各不相同的正整数之和,并且交换顺序视为同一种方法。例如 1000+1001+18 和 1001+1000+18 被视为同一种。

num = 2019
count = 0
# 第一个数从 1 开始
for i in range(1, num):
    # 第二个数要比第一个数大,避免重复
    for j in range(i + 1, num):
        # 计算第三个数
        k = num - i - j
        # 确保第三个数大于第二个数且为正整数
        if k > j and k > 0:
            count = count + 1
print(count)
  

增加条件:要求每个正整数都不包 含数字 2 和 4

num = 2019
count = 0


def check_num(n):
    num_str = str(n)
    return '2' not in num_str and '4' not in num_str


# 第一个数从 1 开始
for i in range(1, num):
    if not check_num(i):
        continue
    # 第二个数要比第一个数大,避免重复
    for j in range(i + 1, num):
        if not check_num(j):
            continue
        # 计算第三个数
        k = num - i - j
        # 确保第三个数大于第二个数且为正整数,同时第三个数不包含 2 和 4
        if k > j and k > 0 and check_num(k):
            count = count + 1

print(count)

五、进制转换

例题一:

小明用字母 A 对应数字1,B 对应2,以此类推,用 Z 对应26。对于27以上的数字,小明用两位或更长位的字符串来对应,例如AA 对应 27,AB 对应28,AZ 对应52,LQ 对 329。请问2019 对应的字符串是什么?

进制转换是指将一个数从一种进制表示转换为另一种进制表示。常见的进制有二进制(满 2 进 1)、十进制(满 10 进 1)、十六进制(满 16 进 1)等。在本题里,使用字母 A - Z 来表示数字,本质上是一种特殊的 26 进制。

word = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
num = 2019
result = ''

while num > 0:
    # 计算当前位对应的字母索引
    remainder = (num - 1) % 26
    # 将对应的字母添加到结果字符串的前面
    result = word[remainder] + result
    # 更新数字,准备计算下一位
    num = (num - 1) // 26

print(result)

例题二:

请找到一个大于 2022 的最小数,这个数转换成十六进制之后,所有的数位(不含前导 0)都为字母(A 到 F)。请将这个数的十进制形式作为答案提交。

import re

n = 2023
while n > 2022:
    result = format(n,'X')
    if re.search(r'\d',str(result)):
        n += 1
    else:
        print(n)
        break

例题三:

在Excel中,列的名称使用英文字母的组合。前 26 列用一个字母,依次为 A 到 Z,接下来 26*26 列使用两个字母的组合,依次为 AA 到 ZZ。请问第 2022 列的名称是什么?

word = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
num = 2022
result = ''

while num > 0:
    digit = (num - 1) % 26
    result = word[digit] + result
    num = (num - 1) // 26
  
print(result)

六、日期问题

例题一:日期遍历与条件统计类

小明坚持每天跑步,正常情况下每天跑一公里,如果这一天是周一或者月初(每月的一号),那么小明就会跑两公里(如果这一天既是周一,又是月初,小明也是跑两公里),小明从2000年1月1日一直坚持到了2020年10月1日,请你计算一下小明共跑了多少公里?

from datetime import date, timedelta

start = date(2000,1,1)
end = date(2020,10,1)
count = 0

while start <= end:
    if start.day == 1 or start.weekday() == 0:
        count += 1
    count += 1
    start = start + timedelta(days=1)

print(count)

例题二:时间戳转换

小蓝要和朋友合作开发一个时间显示的网站。在服务器上,朋友已经获取了当前的时间,用一个整数表示,值为从 1970 年 1 月 1 日 00:00:00 到当前时刻经过的毫秒数。现在,小蓝要在客户端显示出这个时间。小蓝不用显示出年月日,只需要显示出时分秒即可,毫秒也不用显示,直接舍去即可。给定一个用整数表示的时间,请将这个时间对应的时分秒输出。

【输入格式】
输入一行包含一个整数,表示时间。

【输出格式】
输出时分秒表示的当前时间,格式形如 HH:MM:SS,其中 HH 表示时,值为 0 到 23,MM 表示分,值为 0 到 59,SS 表示秒,值为 0 到 59。时、分、秒不足两位时补前导 0。

from datetime import datetime

def timestamp_to_hms(timestamp):
    # 将时间戳转换为 datetime 对象
    dt = datetime.utcfromtimestamp(timestamp)
    # 格式化 datetime 对象,只获取时分秒
    return dt.strftime("%H:%M:%S")


# 示例时间戳(单位:秒)
timestamp = 46800999 // 1000
print(timestamp_to_hms(timestamp))

例题三:回文日期

2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年 2 月 2 日。因为如果将这个日期按 “yyyymmdd” 的格式写成一个 8 位数是 20200202,恰好是一个回文数。我们称这样的日期是回文日期。
有人表示 20200202 是 “千年一遇” 的特殊日子。对此小明很不认同,因为不到 2 年之后就是下一个回文日期:20211202 即 2021 年 12 月 2 日。
也有人表示 20200202 并不仅仅是一个回文日期,还是一个 ABABBABA 型的回文日期。对此小明也不认同,因为大约 100 年后就能遇到下一个 ABABBABA 型的回文日期:21211212 即 2121 年 12 月 12 日。算不上 “千年一遇”,顶多算 “千年两遇”。
给定一个 8 位数的日期,请你计算该日期之后下一个回文日期和下一个 ABABBABA 型的回文日期各是哪一天。

输入格式

输入包含一个八位整数 N,表示日期。

输出格式

输出两行,每行 1 个八位数。第一行表示下一个回文日期,第二行表示下一个 ABABBABA 型的回文日期。

样例输入

20200202

样例输出

20211202
21211212
from datetime import datetime,timedelta

n = str(int(input())+1)
time_n = datetime.strptime(n,'%Y%m%d').date()

times = []
ba_times = []

while True:
    n = datetime.strftime(time_n,'%Y%m%d')
    revers_date = n[::-1]
    if revers_date == n:
        times.append(n)
    ba_date = n[:4][::-1]
    if ba_date[:2] == ba_date[2:] and n[4:6] == n[6:]:
        if ba_date == n[4:]:
            ba_times.append(n)
  
    if len(times) > 1 and len(ba_times) > 1:
        break
    time_n = datetime.strptime(n,'%Y%m%d').date()
    time_n = time_n + timedelta(days=1)

print(times[0])
print(ba_times[0])

例题四:求完全平方数

若一个数是完全平方数,那么它的平方根是一个整数。从2001年1月1日到2021年12月31日中,一共有多少日期中的年月日的数字之和是完全平方数

from datetime import date, timedelta
import math

start = date(2001, 1, 1)
end = date(2021, 12, 31)
count = 0

while start < end:
    total = start.year + start.month + start.day
    sqrt = math.sqrt(total)
    if sqrt ** 2 == total:
        count += 1
    start = start + timedelta(days=1)

print(count)

例题五:扩展数字与汉字对应转换

小蓝决定根据日期的笔画数来安排自己的练习。首先,他会将当天的日期按照 “YYYYMMDD“ 的格式转换成一个 8 位数,然后将这 8 位数对应到汉字上,计算这些汉字的总笔画数。如果总笔画数超过 50,他就去练习篮球;如果总笔画数不超过 50,他就去练习书法。

例如,在 2024 年 1 月 1 日这天,日期可表示为一个 8 位数字 20240101,其转换为汉字是“二零二四零一零一”。日期的总笔画数为 2+13+2+5+13+1+13+1=50,因此在这天,小蓝会去练习书法。

汉字 笔画数
13
1
2
3
5
4
4
2
2
2

现在,请你帮助小蓝统计一下,在 2000 年 1 月 1 日到 2024 年 4 月 13 日这段时间内,小蓝有多少天是在练习篮球?

from datetime import datetime,date,timedelta

num_to_chinese = {
    0: '零', 1: '一', 2: '二', 3: '三', 4: '四',
    5: '五', 6: '六', 7: '七', 8: '八', 9: '九'
}

pen_counts = {}
pen_draw = [13,1,2,3,5,4,4,2,2,2]

for i,v in enumerate(num_to_chinese.values()):
    pen_counts[v] = pen_draw[i]

basket = 0

start = date(2000,1,1)
end = date(2024,4,13)
while start <= end:
    dates = start.strftime('%Y%m%d')
    result = ''
    for j in dates:
        for k in num_to_chinese:
            if int(j) == k:
                result = result + num_to_chinese[k]

    count = 0
    for cn in result:
        for pens in pen_counts:
            if cn == pens:
                count += pen_counts[pens]
    if count > 50:
        basket += 1
  
  
    start = start + timedelta(days=1)

print(basket)

例题六:寻找日期中的 1

小蓝计划在某天的日期中出现 1 时跑 5 千米,否则只跑 1 千米。注意日期中出现 1 不仅指年月日也指星期。

请问按照小蓝的计划,2023 年小蓝总共会跑步锻炼多少千米?例如,5 月 1 日、1 月 13 日、11 月 5 日、4 月 3 日 (星期一) 小蓝会跑 5 千米,而 5 月 23 日小蓝会跑 11 千米 (示例日期均为 2023 年)

from datetime import date,datetime,timedelta

start = date(2023,1,1)
end = date(2024,1,1) - timedelta(days=1)


run = 0
while start <= end:
  
    if '1' in start.strftime('%Y%m%d') or start.weekday() == 0:
        run += 4
    run += 1
    start = start + timedelta(days=1)

print(run)

例题七:求输入日期是今年的第几天

from datetime import date,timedelta

in_date = list(map(int,input().split()))

dates = date(*in_date)
print(dates.timetuple().tm_yday)

七、求质数

质数是指在大于 1 的自然数中,除了 1 和它本身以外不再有其他因数的数

def is_prime(num):
    # 质数定义要求大于 1
    if num < 2:
        return False
    # 从 2 开始到 num - 1 进行遍历
    for i in range(2, num):
        # 如果 num 能被 i 整除,说明 num 不是质数
        if num % i == 0:
            return False
    # 若都不能整除,则 num 是质数
    return True

# 测试示例
test_num = 17
if is_prime(test_num):
    print(f"{test_num} 是质数")
else:
    print(f"{test_num} 不是质数")

例题一:

求300以内的所有质数

def find_primes_brute_force(n):
    primes = []
    for num in range(2, n + 1):
        is_prime = True
        for i in range(2, num):
            if num % i == 0:
                is_prime = False
                break
        if is_prime:
            primes.append(num)
    return primes

# 测试示例
limit = 30
prime_numbers = find_primes_brute_force(limit)
print(f"小于等于 {limit} 的质数有: {prime_numbers}")

八、正则表达式

例题一:

先找出20210605的所有素数,然后判断这些数的十进制位是否都是素数

import re

primes = []
for i in range(2, 20210605 + 1):
    for j in range(2, int(i ** 0.5) + 1):
        if i % j == 0:
            break
    else:
        primes.append(i)

pattern = r'^[2357]+$'

count = 0
for value in primes:
    result = re.search(pattern, str(value))
    if result:
        count += 1

print(count)

埃拉托斯特尼筛法

# 埃拉托斯特尼筛法筛选素数
def sieve_of_eratosthenes(n):
    is_prime = [True] * (n + 1)
    p = 2
    while p * p <= n:
        if is_prime[p]:
            for i in range(p * p, n + 1, p):
                is_prime[i] = False
        p += 1
    primes = []
    for p in range(2, n + 1):
        if is_prime[p]:
            primes.append(p)
    return primes


# 判断一个数是否仅由 2、3、5、7 组成
def is_valid_digits(num):
    num_str = str(num)
    valid_digits = {'2', '3', '5', '7'}
    for digit in num_str:
        if digit not in valid_digits:
            return False
    return True



upper_bound = 20210605
primes = sieve_of_eratosthenes(upper_bound)
count = 0
for prime in primes:
    if is_valid_digits(prime):
        count += 1

print(count)


九、根据数字的位数进行判断

例题一:判断奇偶

输入一个数,判断这个数的奇数位数字是否是奇数(各位、百位、万位...),偶数位数字是否是偶数(十位、千位...)

def check_digits(num):
    num_str = str(num)
    for i, digit in enumerate(num_str):
        digit = int(digit)
        # 判断当前是奇数位还是偶数位
        if (i + 1) % 2 == 1:
            # 奇数位
            if digit % 2 == 0:
                return False
        else:
            # 偶数位
            if digit % 2 == 1:
                return False
    return True


input_num = int(input("请输入一个数: "))
if check_digits(input_num):
    print(f"{input_num} 的奇数位数字是奇数,偶数位数字是偶数。")
else:
    print(f"{input_num} 不满足奇数位数字是奇数,偶数位数字是偶数的条件。")

例题二:判断奇偶2

一个整数如果按从低位到高位的顺序,奇数位 (个位、百位、万位 ⋯ ) 上的数字是奇数,偶数位 (十位、千 位、十万位 ⋯) 上的数字是偶数,我们就称之为 “好数”。给定一个正整数 N,请计算从 1 到 N 一共有多少个好数。

例子:输入 24,输出 7

num = int(input())


def is_odd(n):
    if n % 2 == 0:
        return False
    elif n % 2 != 0:
        return True

def is_even(n):
    if n % 2 == 0:
        return True
    elif n % 2 != 0:
        return False

count = 0
for i in range(1,num+1):
    result = [int(x) for x in str(i)][::-1]
    bools = True
    for idx,val in enumerate(result,start=1):
        if idx % 2 != 0:
            if not is_odd(val):
                bools = False
                break
  
        elif idx % 2 == 0:
            if not is_even(val):
                bools = False
                break
    if bools:
        count += 1
   
print(count)

十、递推问题

例题一:弹珠推放

zhuzi.png

def lei(n):
    if n == 1:
        return 1
    else:
        return n + lei(n-1)

count = 0
ball = 20230610
high = 0

while count < ball:
    # 计算下一个高度所需的弹珠数
    next_count = count + lei(high + 1)
    if next_count > ball:
        break
    high = high + 1
    count = next_count

print(high)

0

评论区