实习编程题,方法比较low,很naive,如有错误,请见谅,望及时指正。
Question #1
有n个小朋友,每个小朋友都有自己的座位。恰好每个小朋友都坐错座位,方式有多少种?
要求算法的复杂度较低,且不考虑整形溢出,其中n<=66。
输入:
第一行:一个自然数,表示小朋友的个数。
输出:
一个整数,表示符合条件的坐法有多少种。
输入范例:
4
输出:
9
分析一波:可以采用分治法的思想。对于小朋友A的位置,剩下有n-1个小朋友都可以坐。若把坐在A小朋友位置上的称作B,那么对于小朋友A此时有两种选择:1.A坐在B的位置上,2.A不坐在B的位置上。对于情形1,剩下的n-2个小朋友看作是一个n=n-2的子问题;对于情形2,A不坐在B位置上,那么我们把位置B现在看作本是A的位置,A不可以坐在这,那就成了一个n=n-1的子问题。基于这种想法,首先想到的是递归的做法:
def f(n):
if n == 1:
return 0
if n == 0:
return 1
return (n - 1) * (f(n-1) + f(n-2))
if __name__ == "__main__":
print(f(4))
但是呢,这种比较暴力的纯递归方法会计算大量的重复子问题,导致复杂度及其高,所以需要寻求更加优化的方法。例如:动态规划。
def f(n):
res = [0 for _ in range(n + 1)]
res[1] = 0
res[2] = 1
for i in range(n-2):
t = i + 3
res[t] = (t - 1) * (res[t-1] + res[t-2])
return res[n]
if __name__ == "__main__":
print(f(4))
Question #2
小明参加数学竞赛,假设小明都会做,但是时间有限,每个题目花费的时间和题目的分数不同,小明需要在考试的有限时间内获得最高的得分。
输入:
第一行:题目的数量
第二行:每个题的分数,空格隔开
第三行:每个题花费的时间,空格隔开
第四行:本场考试的总时间
输出:
小明得的最高分
输入范例:
5
5 4 3 5 2
2 2 3 5 1
10
输出:
16
分析一波:最简单的0-1背包问题。
def f(num, score, time, total_t):
res = [[0 for _ in range(total_t + 1)] for _ in range(num + 1)]
for i in range(num + 1):
if i == 0:
continue
for j in range(total_t + 1):
if j == 0:
continue
if j < time[i]:
res[i][j] = res[i - 1][j]
else:
res[i][j] = max(res[i - 1][j], res[i - 1][j - time[i]] + score[i])
return res[num][total_t]
if __name__ == "__main__":
print(f(5, [0, 5, 4, 3, 5, 2], [0, 2, 2, 3, 5, 1], 10))