《算法导论》第四章后习题4.1-3
交叉点的计算通过20次求两种方法的最小时间差,然后取平均值求得。
以50000个随机元素的列表为例:
暴力法需要约两分钟,分治法需要0.19s,而动态规划只需要0.013s。(单次数据)
import math
import time
import random
def force(profit):
"""
use forceful method
:param profit: profit list
:return: the max profit
"""
maxprofit = 0
for i in range(len(profit)):
for j in range(i + 1, len(profit)):
if profit[j] - profit[i] > maxprofit:
maxprofit = profit[j] - profit[i]
return maxprofit
def fluctuated(profit):
"""
calculate profit list to fluctuated list
:param profit: profit list
:return: fluctuated list
"""
a = []
for i in range(len(profit) - 1):
a.append(profit[i + 1] - profit[i])
return a
def dp(v):
"""
calculate profit list to fluctuated list
:param v: fluctuated list
:return: the max profit
"""
add = v[0]
res = add
for i in range(1, len(v)):
if add > 0:
add += v[i]
else:
add = v[i]
res = max(res, add)
return res
# class Result:
# """
# ans : max sum
# sub : max subarray
# low
# high
# """
# ans = 0
# low = high = 0
#
# def __init__(self, ans, low, high):
# self.low = low
# self.high = high
# self.ans = ans
def find_cross_subarray(v, low, high):
"""
find cross subarray
:param v: volatility list
:param low: lower-bound
:param high: upper-bound
:return: an object includes subarray and max sum
"""
lsum = -9999999999
add = 0
mid = math.floor((low + high) / 2)
max_right = max_left = 0
for i in range(mid, low - 1, -1):
add += v[i]
if add > lsum:
lsum = add
max_left = i
rsum = -99999999999
add = 0
for j in range(mid + 1, high):
add += v[j]
if add > rsum:
rsum = add
max_right = j
return lsum + rsum, max_left, max_right
def find_max_sub(v, low, high):
"""
:param v: a fluctuated list
:param low: list's lower-bound
:param high: list's upper-bound
:return: the max subarray-info
"""
if high == low:
return v[low], low, high
else:
mid = math.floor((low + high) / 2)
(left_sum, left_low, left_high) = find_max_sub(v, low, mid)
(right_sum, right_low, right_high) = find_max_sub(v, mid + 1, high)
(cross_sum, cross_low, cross_high) = find_cross_subarray(v, low, high)
# compare
if left_sum >= right_sum and left_sum >= cross_sum:
return left_sum, left_low, left_high
elif right_sum >= left_sum and right_sum >= cross_sum:
return right_sum, right_low, right_high
else:
return cross_sum, cross_low, cross_high
def get_random_list(size, lower, upper):
"""
generate a random array
:param size: size
:param lower: bound
:param upper: bound
:return: random array
"""
arr = []
i = 0
while i < size:
arr.append(random.randint(lower, upper))
i += 1
return arr
def exe_time(size, times):
"""
generate a <size>-length random array,and test two method by <times> times;
:param size: random array's size
:param times: execute times
:return: two methods' time diff
"""
random_arr = get_random_list(size, 10000, 1000000)
f_arr = fluctuated(random_arr)
force_start = time.time()
for i in range(times):
force(random_arr)
force_end = time.time()
force_last = force_end - force_start
div_start = time.time()
for i in range(times):
find_max_sub(f_arr, 0, len(f_arr) - 2)
div_end = time.time()
div_last = div_end - div_start
# print("Force-last:" + "%s" % force_last)
# print("div-last:" + "%s" % div_last)
return abs(div_last - force_last)
def test_intersection(times):
"""
find two methods' crosspoint
execute 20 times and calculate the averager
:return: intersection
"""
i = 0
add_times = 0
while i < 20:
j = 60
inter = j
min_diff = exe_time(j, times)
while j > 10:
j -= 1
diff = exe_time(j, times)
if diff < min_diff:
min_diff = diff
inter = j
# print("diff:%-30s" % diff, "times:%s" % i)
print("intersections:", inter)
add_times += inter
i += 1
return add_times / 20
def main():
print("Average:", test_intersection(70))
# print(exe_time(10, 10000))
# RandomArr = get_random_list(50000, 10000, 1000000)
# FArr = fluctuated(RandomArr)
# print(RandomArr)
# t_start = time.time()
# Max = force(RandomArr)
# t_end = time.time()
# print("%-15s" % "Method", "%-15s" % "Result", "Time")
# print("%-15s" % "Force", "%-15s" % Max, t_end - t_start)
#
# t_start = time.time()
# (res, l, h) = find_max_sub(FArr, 0, len(RandomArr) - 2)
# t_end = time.time()
# print("%-15s" % "Div_Recursion", "%-15s" % res, t_end - t_start)
#
# t_start = time.time()
# Max = dp(FArr)
# t_end = time.time()
# print("%-15s" % "DP", "%-15s" % Max, t_end - t_start)
if __name__ == '__main__':
main()