Python 实验题目

实验一

1. 设计算法求数组中相差最小的两个元素(称为最接近数)的差。

import math


def tcn(n):
    # 对列表进行排序
    n.sort()
    # 初始化最接近数的最小值为无穷大
    m = math.inf
    # 双指针初始化
    i = 0
    # 遍历循环列表,当j+1大于列表的长度时结束循环
    while i <= len(n)-2:
        j = i + 1
        c = n[j] - n[i]
        # 进行最小值替换
        if c < m: m = c
        i += 1
    # 返回最小值
    return m


l = int(input("请输入数组的长度:"))
print("输入数组:")
n = [int(input()) for i in range(l)]
m = tcn(n)
print("该数组的最接近数的差为;", m)

实验二

1. 设计算法,判断一个大整数能否被11整除。可以通过以下方法:将该数的十进制表示从右端开始,每两位一组构成一个整数,然后将这些数相加,判断其和能否被11整除。例如,将562843748分割成5,62,84,37和48,然后判断(5+62+84+37+48)能否被11整除。

def z(n):
    # 将接收到的整数n转换为字符串形式m
    m = str(n)
    # 判断字符串的长度是否是偶数还是奇数,初始化定义遍历列表的指针i,整数s
    if len(m) % 2 == 0:
        # 如果字符串的长度为偶数,则i=0,s=0
        i = 0
        s = 0
    else:
        # 如果字符串的长度为奇数,则i = 1,s = int(m[0])
        i = 1
        s = int(m[0])
    while i < len(m):
        # 通过指针i遍历整个数组,不断的对m进行切片并累加到s中
        s += int(m[i:i + 2])
        i += 2
    # 最后判断s是否被11整除,能则大整数能被11整除,反之则不能
    if s % 11 == 0:
        print("{} 能被11整除!".format(n))
    else:
        print("{} 不能被11整除!".format(n))


z(input("请输入一个大整数:"))

2. 设计算法,在数组r[n]中删除重复的元素,要求移动元素的次数较少并使剩余元素间的相对次序保持不变。

def dl(r):
    # 定义接收的列表
    n = []
    # 遍历输入的列表r
    for i in r:
        # 如果列表r中的元素不在列表n中则添加到n中
        if i not in n:
            n.append(i)
        # 否则则不进行添加
    # 返回删除重复元素后的列表n
    return n


l = int(input("请输入数组的长度:"))
print("请输入数组r:")
r = [int(input()) for i in range(l)]
print("删除重复的元素之前的列表为:", r)
print("删除重复的元素之后的列表为:", dl(r))

3. 已知数组A[n]的元素为整型,设计算法将其调整为左右两部分,左边所有元素为奇数,右边所有元素为偶数,要求时间复杂度为O(n),空间复杂度O(1)。

def jo(A):
    # 初始化列表a都为0,长度和列表A一样
    a = [0 for _ in range(len(A))]
    # 初始化双指针,分别指向列表a的头和尾
    i, j = 0, len(A) - 1
    # 遍历列表A,k指向列表A中的元素
    for k in A:
        # 判断元素k是否为奇数
        # 是则从前往列表a中加
        if k % 2 != 0:
            a[i] = k
            i += 1
        # 否则就从列表a尾巴往前面加
        else:
            a[j] = k
            j -= 1
    # 返回调整之后的列表a
    return a


l = int(input("请输入数组A的长度:"))
print("请输入列表的元素:")
A = [int(input()) for i in range(l)]
print("调整前:", A)
print("调整后:", jo(A))

4. 设计蛮力算法求解小规模的线性规划问题。假设约束条件:①x + y <= 34;②x+3*y <= 6; ③x >= 0 且 y >= 0,使目标函数3*x + 5*y取得极大值。 

m = 0
# 蛮力法求解
for x in range(5):
    for y in range(3):
        # 与最大值进行比较
        if m < 3 * x + 5 * y:
            if x + y <= 4 and x + 3 * y <= 6:
                m = 3 * x + 5 * y
print("极大值为:", m)

实验三

1. 设计分治算法,实现将数组A[n]中所有元素循环左移k个位置,要求时间复杂度为O(n),空间复杂度为O(1)。例如,对abcdefgh循环左移三位得到defghabc。

def rv(A, k):
    # 列表A的长度
    l = len(A)
    # 判断需要向左移的位数,如果大于等于列表A的长度l,则需要进行取余操作,即k = k % l
    if k >= l:
        k = k % l
    # 此处采用列表特有的列表切片进行操作,再将列表进行组合
    A = A[k:] + A[:k]
    # 返回移动之后的列表
    return A


k = int(input("请输入向左移的位数:"))
n = int(input("数组A的元素个数:"))
print("请输入元素:")
A = [input() for i in range(n)]
print("移动之前:" + "".join(A))
print("移动之后:" + "".join(rv(A, k)))

2. 设a1,a2,…,an是集合{1,2,3,…,n}的一个全排列,如果i<j且ai>aj,则序偶(ai,aj)称为该排列的一个逆序。例如,2,3,1有两个逆序:(3,1)和(2,1)。设计算法统计给定排序中含有逆序的个数。 

def nx(a):
    # 获取列表a的长度
    l = len(a)
    # 定义一个空列表用来存储逆序列
    b = []
    # 指针i指向a中的元素
    for i in range(l-1):
        # 指针k指向指针i后面的元素
        for j in range(i+1, l):
            # 判断指针i和j指向的元素是否满足逆序的条件
            if a[i] > a[j]:
                # 满足添加到列表b中
                c = (a[i], a[j])
                b.append(c)
    # 返回所有满足的逆序
    return b


n = int(input("请输入列表的元素个数:"))
print("请输入列表元素:")
a = [int(input()) for i in range(n)]
print("逆序有:{},一共有{}个。".format(nx(a), len(nx(a))))

实验四

1. 设计折半查找算法,在有序序列{7,14,18,21,23,29,31,35,38}中查找18。

def zb(a, k):
    # 定义双指针进行位置的确定(首和尾)
    i = 0
    j = len(a) - 1
    # 开始遍历数组,当两指针指向同一个数时终止循环
    while(i <= j):
        # 找到两指针的中间位置(注意有可能为小数,进行取整)
        mid = (i + j) // 2
        # 对目标值的位置进行判断
        if k < a[mid]:
            j = mid - 1
        elif k > a[mid]:
            i = mid + 1
        else:
            return mid + 1
    # 返回最终值的位置
    return i-1
 
n = int(input("请输入数组的个数:"))
k = int(input("查找的元素:"))
print("请输入数组中的{}个数:".format(n))
a = [int(input()) for i in range(n)]
m = zb(a, k)
print("您需要查找的数{}在数组中的位置为{}".format(k, m))

2. 修改折半查找算法使之能够进行范围查找。所谓范围查找是要在找出给定值a和b之间的所有元素(a小于等于b) 

def zb(a, x, y):
    # 列表结果存储
    o = []
    # 定义双指针进行位置的确定(首和尾)
    i = 0
    j = len(a) - 1
    # 开始遍历数组,当两指针指向同一个数时终止循环
    while(i <= j):
        # 找到两指针的中间位置(注意有可能为小数,进行取整)
        mid = (i + j) // 2
        # 对目标值的位置进行判断
        if y < a[mid]:
            j = mid - 1
        elif x > a[mid]:
            i = mid + 1
        else:
            # 因为此时中间数是范围中的,因此在此处直接进行添加在列表结果中
            for k in range(i,j):
                if x<= a[k] <= y:
                    o.append(k)
            return o
 
n = int(input("请输入数组的个数:"))
print("请输入范围:")
x = int(input())
y = int(input())
print("请输入数组中的{}个数:".format(n))
a = [int(input()) for i in range(n)]
m = zb(a, x, y)
print("范围在{}到{}在数组中的位置是从{}到{}".format(x, y, m[0], m[1]))
print("数组中的数分别为:", end = '')
for i in m:
    print(a[i], end = ' ')

实验五

1 设有n个顾客同时等待一项目服务,顾客i 需要的服务时间为ti(1≤i≤n) ,如何安排n个顾客的服务次序才能使顾客总的等待时间达到最小?

def jy(n, x):
    # 加油的次数
    count = 0
    # 汽车的剩余油量
    y = n
    # 开始行使
    for i in range(len(x)-1):
        # 到达一个加油站
        y -= x[i]
        # 判断是否需要加油
        if y > x[i+1]:
            # 不需要,继续走
            continue
        else:
            # 需要,输出这是第几个加油站,并统计加油一次
            print(f"这个是第{i+1}个加油站")
            count += 1
            # 加满油
            y = n
    # 输出加油的次数
    return count
 
 
n = int(input("请输入加满油之后车能跑多远:"))
k = int(input("请输入有多少个加油站:"))
print("请输入距离:")
x = [int(input()) for i in range(k+1)]
print(f"总共加油次数:{jy(n,x)}")

2 在0/1背包问题中,假设各物品按重量递增排列时,其价值恰好按递减排列,对于这个特殊的0/1背包问题,设计一个有效的算法找出最优解。

# 从键盘输入中得到物品的体积和价值
def qu(N):
    for i in range(N):
        x = [int(j) for j in input().split()]
        v.append(x[0])
        w.append(x[1])
    return v, w
 
 
# 获取最大的价值
def max_():
    for i in range(1, n+1):  # 有几个物品可供选择
        for j in range(1, m + 1):  # 模拟背包容量从m+1
            if j < v[i-1]:  # 如果此时背包容量小于当前物品重量
                f[i][j] = f[i - 1][j]  # 不拿这个物品
            else:
                # 此时有两种选择,拿或不拿
                f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i - 1]] + w[i-1])
                # 选择最好的一种方式,也就是两种情况作比较,取价值的较大值
 
 
# 取得物品的个数和背包的总体积
a = [int(i) for i in input().split()]
# 物品的个数
n = a[0]
# 背包总体积
m = a[1]
# 各个物品的体积列表
v = []
# 对应物品的价值
w = []
# 将物品的体积和价值装入列表中
qu(n)
# 模拟背包
f = [[0] * (m + 1) for _ in range(n + 1)]
# 获取最大的价值
max_()
print(f[n][m])

3 一辆汽车加满油后可行驶n公里,旅途中若干个加油站,加油站之间的距离由数据A[m]给出,其中A[i]表示第i-1个加油站和第i个加油站的距离,旅途的起点和终点都各有一个加油站。设计一个有效的算法,计算沿途需要停靠加油的地方,使加油次数最少。

def sj(t):
    # 列表存储每一位顾客的等待时间
    a = [0 for i in range(len(t))]
    # 将顾客等待时间按照时间进行排序
    t = sorted(t, key = lambda x:x[0])
    # 遍历顾客时间,并对每一位顾客的时间进行累加
    for i in range(len(t)):
        # 输出每次进行服务的顾客是第几位
        print("第{}次服务第{}个顾客。".format(i+1,t[i][1]+1))
        for j in range(i,len(t)):
             a[j] += t[i][0]
    # 返回最后的总时间
    return sum(a)
 
 
# 输入顾客的数量
n = int(input("请输入顾客的人数:"))
print("请输入每个顾客服务的时间:")
# 输入每一个顾客进入的次序和服务时间
t = [[int(input()),i] for i in range(n)]
# 进行统计总的等待时间
tz = sj(t)
# 输出平均时间
print("顾客平均等待时间:",tz/n)

实验六

1. 跳跃游戏II 

class Solution(object):
    def jump(self, nums):
        # 设置初始的值
        m, n, t, = 0, 0, 0
        # 开始遍历,贪心每次找到局部最优,通过局部最优找到全局最优
        # 遍历时不访问最后一个元素
        for i in range(len(nums) - 1):
            if m >= i:
                m = max(m, i + nums[i])
                if i == n:
                    n = m
                    t += 1
        return t

2. 买卖股票的最佳时机

class Solution:
    def maxProfit(self, prices):
        # 定义无穷最低价格为无穷大
        minprice = int(1e9)
        # 初始化最大利润为0
        maxlr = 0
        # 循环遍历一次价格列表
        for price in prices:
            # 判断此时对应的利润与最大利润大小,选取大的利润
            maxlr = max(price - minprice, maxlr)
            # 比较现在的价格的以前的价格大小
            minprice = min(price, minprice)
        # 因为是从开始到结束一遍结束,因此输出最大利润即可
        return maxlr

实验七

1. 爬楼题

class Solution:
    def climbStairs(self, n: int) -> int:
        # 如果n小于三直接输出n
        if n <= 3:
            return n
        # 初始定义两个初值
        a, b = 2, 3
        # 每一次进行交换
        for i in range(2,n):
            a, b = b, a+b
        # 返回计算得出的值
        return a

2. 硬币 

# 硬币
class Solution:
    def waysToChange(self, n: int) -> int:
        mod = 10**9 + 7
        coins = [25, 10, 5, 1]

        f = [1] + [0] * n
        for coin in coins:
            for i in range(coin, n + 1):
                f[i] += f[i - coin]
        return f[n] % mod

实验八

1. 有面值为(v1, v1, ..., vn )的n种纸币,需要支付y值的纸币,应如何支付才能使纸币支付的张数最少,即满足i=1nxivi=y,且使i=1nxi最小。设计动态规划算法求解付款问题。

n = int(input("请输入货币种类的个数:"))
print("从小到大输入货币的价值,其中第一个必须为一")
h = [0] + [int(input()) for i in range(1, n+1)]
z = int(input("输入要兑换的钱的价值:"))
a = [[0] * (n+1) for _ in range((z+1))]
for i in range(1, z+1):
    for j in range(1, n+1):
        if h[j] == i:
            a[i][j] = 1
        elif h[j] > i:
            a[i][j] = a[i][j - 1]
        else:
            a[i][j] = a[i - h[j]][j] + 1
print(f"兑换的最小货币张数是:{a[z][n]}")

2. 给定一个正整数集合X={x1, x2,  ...  , xn}和一个正整数y,设计回溯算法,求集合X的一个子集Y,使得Y中元素之和等于y。

def ziji(X, y):
    i = 0
    # 存储目标子集
    Y = []
    while i < len(X):
        # 开始遍历全集
        j = i
        # 将产生出来的所有子集进行存储
        yi = []
        # 开始遍历
        for k in range(j, len(X)):
            # 将现有的子集放入子集列表中
            yi.append(X[k])
            # 如果刚好等于我们需要计算得出的数,直接将此子集进行存储,终止此次循环
            if sum(yi) == y:
                Y.append(yi)
                break
            # 如果大于我们需要计算的数,则也终止此次循环
            if sum(yi) > y:
                break
        # 继续往后面走
        i += 1
    return Y


n = int(input("请输入集合元素的个数:"))
X = [int(input()) for i in range(n)]
y = int(input("请输入求和的结果为:"))
Y = ziji(X, y)
print(f"所有子集为:{Y}")

3. 桥本分数。把{1,2,…,9}这九个数字填入下图所示的9个方格中,使得等式成立,要求数字不得重复。

# 将输入的数列表进行全排列,并输出全排列
def qpl(nums):
    res = []
    def back(nums_all, temp):
        if len(nums_all) == 0:
            res.append(temp)
            return
        for i in range(len(nums_all)):
            back(nums_all[:i] + nums_all[i + 1:], temp + [nums_all[i]])
    t = []
    back(nums, t)
    return res

# 输入1到9
a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
# 得到全排列的结果
x = qpl(a)
y = []
# 将除法转换为乘法
for i in x:
    # 防止出现3+7=10,7+3=10的情况
    if i[0] < i[3]:
        x1, x2 = i[0], i[1] * 10 + i[2]
        y1, y2 = i[3], i[4] * 10 + i[5]
        z1, z2 = i[6], i[7] * 10 + i[8]
        # 满足相等的情况则将信息存入
        if x1 * y2 * z2 + x2 * y1 * z2 == x2 * y2 * z1:
            y.append(i)
# 输出最后的结果
print(f"解的个数为:{len(y)}")
for i in range(len(y)):
    print(f"第{i + 1}个解为:{y[i]}")

4 设某一机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得。设wij是从供应商j 处购得的部件i的重量,cij是相应的价格。试设计一个回溯算法,给出总价格不超过d的最小重量机器设计。对于给定的机器部件重量和机器部件价格,计算总价格不超过d的最小重量机器设计。

def hs(t):
    # 定义全局变量,防止在回溯过程中重复定义
    global n, m, w, v, min_w, min_v, best_w, best_v, best_x
    if t >= n:
        # 条件更优时,更新数据
        if min_v <= d and min_w < best_w:
            best_w, best_v = min_w, min_v
            for j in range(n):
                best_x[j] = x[j]
    else:
        for j in range(m):
            # 记录下当前部件是哪一个供应商
            x[t] = j
            min_w = min_w + w[t][j]
            min_v = min_v + v[t][j]
            # 剪枝
            if min_v <= d and min_w < best_w:
                # 如果当前供应商的部件可以满足条件 直接进入下一个部件的判断
                hs(t + 1)
            # 回溯过程
            min_w = min_w - w[t][j]
            min_v = min_v - v[t][j]
    return best_w, best_x


# 输入机器部件数、供应商数、计算总价值不超过d的值
n, m, d = [int(i) for i in input("请输入机器部件数、供应商数、计算总价值不超过d的值:").split()]
# 各表示从供应商j处购得部件i的价格/重量
v = [[int(i) for i in input().split()] for _ in range(n)]
w = [[int(i) for i in input().split()] for _ in range(n)]
# 定义存储当前最小的重量和价值的变量
min_w, min_v = 0, 0
# 定义最优的最小重量和价值(初始化为999)
best_w, best_v = 999, 999
# 定义存储提供部件的供应商以及最优供应商
x, best_x = [0 for _ in range(m)], [0 for _ in range(m)]
hs(0)
print(f"最优重量:{best_w},最优的供应商:{[i+1 for i in best_x]}")
一个机器人只能向下和向右移动,每次只能移动一步,设计一个算法求机器人从(0,0)到(m,n)有多少条路径。
def lj(n, m):
    # 利用回溯法进行不断的获取路径
    if n == 1 and m == 1:
        return 1
    elif n == 1:
        return lj(n, m - 1)
    elif m == 1:
        return lj(n - 1, m)
    else:
        return lj(n - 1, m) + lj(n, m - 1)


n = int(input("请输入n:"))
m = int(input("请输入m:"))
print(f"机器人从(0,0)到(m,n)有:{lj(n, m)}条路径")

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值