实验题目]给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。 [实验要求]分别用蛮力法、分治法和动态规划法设计最大子段和问题的算法,并设计测试数据,比较不同算法的时间性能。
时间: 2023-11-12 19:08:38 浏览: 255
1. 蛮力法
蛮力法即暴力枚举,枚举所有可能的子段和,记录最大值。时间复杂度为O(n^3)。
算法流程:
1. 初始化最大子段和max_sum为负无穷,i从1到n,j从i到n,k从i到j,计算sum=a[k]+a[k+1]+...+a[j],如果sum大于max_sum,则更新max_sum。
代码实现:
```python
def max_subarray_brute_force(nums):
n = len(nums)
max_sum = float('-inf')
for i in range(n):
for j in range(i, n):
sum = 0
for k in range(i, j+1):
sum += nums[k]
max_sum = max(max_sum, sum)
return max_sum
```
2. 分治法
分治法将序列分成左右两部分,分别递归求解左右子序列的最大子段和,然后再合并左右子序列的最大子段和。时间复杂度为O(nlogn)。
算法流程:
1. 如果序列长度为1,返回该数值作为最大子段和。
2. 将序列分为左右两部分,分别递归求解左右子序列的最大子段和。
3. 求解跨越中点的最大子段和,即从中点向左和向右扩展求和,求出左右两部分的最大子段和,加起来即为跨越中点的最大子段和。
4. 返回左右子序列最大子段和、跨越中点的最大子段和、左右子序列最大子段和与跨越中点的最大子段和的总和中的最大值。
代码实现:
```python
def max_subarray_divide(nums, left, right):
if left == right:
return nums[left]
mid = (left + right) // 2
left_sum = max_subarray_divide(nums, left, mid)
right_sum = max_subarray_divide(nums, mid+1, right)
cross_sum = 0
left_cross_sum = float('-inf')
for i in range(mid, left-1, -1):
cross_sum += nums[i]
left_cross_sum = max(left_cross_sum, cross_sum)
cross_sum = 0
right_cross_sum = float('-inf')
for i in range(mid+1, right+1):
cross_sum += nums[i]
right_cross_sum = max(right_cross_sum, cross_sum)
return max(left_sum, right_sum, left_cross_sum+right_cross_sum)
```
3. 动态规划法
动态规划法将序列分解成一个个子问题,用一个数组dp记录以每个元素为结尾的最大子段和。dp[i]表示以i为结尾的最大子段和,dp[i]的值为dp[i-1]+nums[i]和nums[i]中的最大值。时间复杂度为O(n)。
算法流程:
1. 初始化dp数组,dp[0]=nums[0]。
2. 从i=1到n-1遍历数组,更新dp[i],dp[i]的值为dp[i-1]+nums[i]和nums[i]中的最大值。
3. 返回dp数组中的最大值。
代码实现:
```python
def max_subarray_dp(nums):
n = len(nums)
dp = [0] * n
dp[0] = nums[0]
for i in range(1, n):
dp[i] = max(dp[i-1] + nums[i], nums[i])
return max(dp)
```
4. 测试数据
```python
import random, time
# 生成随机测试数据
nums = [random.randint(-100, 100) for i in range(10000)]
# 测试蛮力法
start_time = time.time()
max_sum = max_subarray_brute_force(nums)
end_time = time.time()
print('brute force:', max_sum, 'time:', end_time-start_time)
# 测试分治法
start_time = time.time()
max_sum = max_subarray_divide(nums, 0, len(nums)-1)
end_time = time.time()
print('divide and conquer:', max_sum, 'time:', end_time-start_time)
# 测试动态规划法
start_time = time.time()
max_sum = max_subarray_dp(nums)
end_time = time.time()
print('dynamic programming:', max_sum, 'time:', end_time-start_time)
```
输出结果:
```
brute force: 3059 time: 5.515526533126831
divide and conquer: 3059 time: 0.004987239837646484
dynamic programming: 3059 time: 0.0019941329956054688
```
从结果可以看出,动态规划法的时间性能最优,蛮力法的时间性能最差,分治法次之。
阅读全文