题目1:给定一个有序数组arr,代表数轴上从左到右有n个点arr[0],arr[1]...arr[n-1],给定一个正数L,代表一根长度为L的绳子,求绳子最多能覆盖其中的几个点。
解题思路:使用滑动窗口的方法,通过维护一个窗口,使得窗口内覆盖的值最大,当下一个参数减去窗口的最左边的值小于绳子的长度L,则窗口的最右边往右滑一步,否则窗口的最左边往右滑。
def num1(arr,L):
N = len(arr)
left, right = 0, 0
m = 0
while left < N :
while right < N and arr[right]-arr[left]<=L:
right+=1
m = max(m, right-left)
left+=1
return m
arr = [2,4,8,9,12,17]
L = 5
k = num1(arr,L)
题目2:小虎去附近的商店买苹果,奸诈的商贩使用了捆绑交易,只提供6个每袋和8个每袋的包装包装不可拆分。可是小虎现在只想购买恰好n个苹果,小虎想购买尽量少的袋数方便携带。如果不能购买恰好n个苹果,小虎将不会购买。输入一个整数n,表示小虎想购买的个苹果,返回最小使用多少袋子。如果无论如何都不能正好装下,返回-1。
解题思路:先尽量使用8类型的袋子,看剩下的苹果能不能被6类型的袋子装完,不行就8类型的袋子减一,继续看剩下的苹果能不能被6类型的袋子装完,试完都不行的话返回-1,N为奇数的话也不行。当我剩余的苹果数一旦超过24以上,下面的都不成立,剩余的24个苹果要用6类型的袋子搞定,而8类型也可以搞定这24个苹果。24是6和8的最小公倍数。
def num2(apple):
if apple<0:
return -1
bag6 = -1
bag8 = apple//8
rest = apple-bag8*8
while (bag8>=0 and rest < 24):
restuse6 = rest/6 if rest % 6==0 else -1
if restuse6 != -1:
bag6 = restuse6
break
bag8-=1
rest = apple - bag8*8
return -1 if bag6==-1 else bag8+bag6
print(num2(14))
方法2:打表法,当题目输入参数为整数,输出结果也为整数,观察输出的结果,通过数学规律写出代码,即为最优解。
def num22(apple):
# 奇数返回-1
if apple % 2!=0: return -1
if apple<18:
if apple ==0: return 0
elif apple==6 or apple==8: return 1
elif apple==12 or apple==14 or apple==16: return 2
else: return -1
return (apple - 18) / (8+3)
print(num22(14))
题目3:
解题思路:
for循环每一步都进行枚举,时间复杂度太高;可以创建数组AB,分别记录0-i有多少个R和i-N-1有多少个G,计算的时候直接拿即可。
知识点:预处理数组,用空间换时间。
def num3(color):
color = list(color)
N = len(color)
A = [0]*N # 记录0 - i有多少个G
B = [0]*N # 记录i - N-1有多少个R
N = len(color)
for i in range(N-1, -1, -1):
if color[i] == 'R':
B[i] = 1 if i == N-1 else B[i+1] + 1
else:
B[i] = 0 if i == N-1 else B[i+1]
# 赋值B[0],全部染成G的情况
res = B[0]
for i in range(N):
if color[i] == 'G':
A[i] = 1 if i == 0 else A[i-1] + 1
else:
A[i] = 0 if i == 0 else A[i-1]
# 记录最小值,i==N-1时,全部染成G的情况
res = min(res, A[i]) if i == N-1 else min(res, A[i] + B[i+1])
return res
str = 'RRRRR'
print(num3(str))
题目4:
解题思路:
1.从下往上,从右往左建立right矩阵,计该点右边有多少个连续的1;从下往上建立down矩阵,计算该点从下往上有多少个连续的1。创建预处理数组,省去了在里面建立四个for循环判断是都为1的时间。
2.当确认左上方顶点时,可以通过矩阵查询右上角点,左下角点是否都符合条件。
def num4(arr):
N = len(arr) # 行
M = len(arr[0]) # 列
if N < 1: return 0
right = np.zeros((N, M))
down = np.zeros((N, M))
# 创建right数组
for row in range(N):
for col in range(M-1, -1, -1):
if arr[row][col] == 1:
right[row][col] = 1 if col == M-1 else right[row][col+1] + 1
else:
right[row][col] = 0
# 创建down数组
for col in range(M):
for row in range(N-1, -1, -1):
if arr[row][col] == 1:
down[row][col] = 1 if row == N - 1 else down[row+1][col] + 1
else:
down[row][col] = 0
res = 0
for row in range(N):
for col in range(M):
maxBorder = min(N - row, M - col)
for border in range(1, maxBorder+1):
if right[row][col] >= border and down[row][col] >= border and down[row][int(col+border-1)] >= border and right[int(row+border-1)][col]>=border:
res = max(res, border)
return res
arr = [[1,0,1,1,1],[1,0,1,0,1],[1,1,1,1,1],[1,0,1,0,0]]
print('border',num4(arr))
题目5:
解题思路:
1.首先利用f函数生成等概率返回0、1的函数,例如在1-5中,f返回1、2返回0,f返回3、4返回1,f返回5重新进入f。
2.再确定1-7需要7个数字,至少要3位二进制数字,构造返回值位0-6的函数,利用01函数生成三位二进制数,当其大于6时候重新生成。
3.该函数生成01或者10的概率都为p*(1-p),因此生成数字位01返回0,生成数字位10返回1,生成数字位00或11重新生成。