最大子序列的不同时间复杂度算法
2013-06-27 10:03
183 查看
1.求一个序列的最大子序列和的算法时间复杂度为O(n^3),即枚举算法,也就是说:将原序列的每个子序列枚举出来并求和,最后从中找出一个最大值,算法如下:
long maxSubSum(const long *a)
{
long max =
0;
for (int i
= 0; i < a.size(); i++)
{
for (int j
= i; j < a.size(); j++)
{
long sum
= 0;
for (int k
= i; k <= j; k++)
{
sum
+= a[k];
}
if (sum
> max)
sum
= Sum;
}
}
return max;
}
2. 时间复杂度为O(n^2)。此算法是先在以第i个元素a[i]开始(包含a[i])的子序列中找到一个最大子序列和,然后再从这些最大子序列和中找出最大的一个子序列和,即为原序列的最大子序列和。
long maxSubSum(const long *a)
{
long max =
0;
for (int i
= 0; i < a.size(); i++)
{
long sum = 0;
for (int j
= i; j < a.size(); j++)
{
sum += a[j];
if(sum > max)
max = sum;
}
}
return max;
}
3. 时间复杂度为O(nlgn)。此算法主要采用了“分治思想”,一个序列的是最大子序列出现的位置只有三种情况:i) 在原序列的最左半部分,ii)在原序列的最右半部分,iii)横跨序列中部的占据序列左右两个部分。前两种情况递归求解,第三种情况的最大和可以通过求出前半部分最大和(包含前半部分最后一个元素)以及后半部分最大和(包含后半部分的第一个元素)相加而得到。
long maxSumRec(const long *a, int l, int r)
{
if (l ==
r)
{
if (a[l]
> 0)
return a[l];
else
return 0;
}
int center
= (l + r) / 2;
long maxLeftSum
= maxSumRec(a, l, center);
long maxRightSum
= maxSumRec(a, center+1, r);
//求出以左边最后一个数字为尾的序列最大值
long maxLeftBorderSum
= 0, leftBorderSum = 0;
for (int i
= center; i >= l; i--)
{
leftBorderSum
+= a[i];
if (leftBorderSum
> maxLeftBorderSum)
maxLeftBorderSum
= leftBorderSum;
}
//求出以右边第一个数字开始的序列最大值
long maxRightBorderSum
= 0, rightBorderSum = 0;
for (int j
= center+1; j <= r; j++)
{
rightBorderSum
+= a[j];
if (rightBorderSum
> maxRightBorderSum)
maxRightBorderSum
= rightBorderSum;
}
//返回三者中的最大值
return max(maxLeftSum,
maxRightSum,
maxLeftBorderSum
+ maxRightBorderSum);
}
long maxSubSum(const
long *a)
{
return maxSumRec(a,
0, a.size()-1);
}
//求出三个long中的最大值
long max(long a, long b, long c)
{
if (a
< b)
{
a
= b;
}
if (a
> c)
return a;
else
return c;
}
4. 时间复杂度为O(n). 此算法是一个线性时间的算法,程序较为简单,但是不容易理解其正确性。简单地说,最大子序列不可能以和为负数的子序列为前缀的。
long maxSubSum(const
long *a)
{
long max =
0, sum = 0;
for (int j
= 0; j < a.size(); j++)
{
sum
+= a[j];
if (sum
> max )
max
= sum;
else if (sum
< 0)
sum
= 0;
}
return max
;
}
long maxSubSum(const long *a)
{
long max =
0;
for (int i
= 0; i < a.size(); i++)
{
for (int j
= i; j < a.size(); j++)
{
long sum
= 0;
for (int k
= i; k <= j; k++)
{
sum
+= a[k];
}
if (sum
> max)
sum
= Sum;
}
}
return max;
}
2. 时间复杂度为O(n^2)。此算法是先在以第i个元素a[i]开始(包含a[i])的子序列中找到一个最大子序列和,然后再从这些最大子序列和中找出最大的一个子序列和,即为原序列的最大子序列和。
long maxSubSum(const long *a)
{
long max =
0;
for (int i
= 0; i < a.size(); i++)
{
long sum = 0;
for (int j
= i; j < a.size(); j++)
{
sum += a[j];
if(sum > max)
max = sum;
}
}
return max;
}
3. 时间复杂度为O(nlgn)。此算法主要采用了“分治思想”,一个序列的是最大子序列出现的位置只有三种情况:i) 在原序列的最左半部分,ii)在原序列的最右半部分,iii)横跨序列中部的占据序列左右两个部分。前两种情况递归求解,第三种情况的最大和可以通过求出前半部分最大和(包含前半部分最后一个元素)以及后半部分最大和(包含后半部分的第一个元素)相加而得到。
long maxSumRec(const long *a, int l, int r)
{
if (l ==
r)
{
if (a[l]
> 0)
return a[l];
else
return 0;
}
int center
= (l + r) / 2;
long maxLeftSum
= maxSumRec(a, l, center);
long maxRightSum
= maxSumRec(a, center+1, r);
//求出以左边最后一个数字为尾的序列最大值
long maxLeftBorderSum
= 0, leftBorderSum = 0;
for (int i
= center; i >= l; i--)
{
leftBorderSum
+= a[i];
if (leftBorderSum
> maxLeftBorderSum)
maxLeftBorderSum
= leftBorderSum;
}
//求出以右边第一个数字开始的序列最大值
long maxRightBorderSum
= 0, rightBorderSum = 0;
for (int j
= center+1; j <= r; j++)
{
rightBorderSum
+= a[j];
if (rightBorderSum
> maxRightBorderSum)
maxRightBorderSum
= rightBorderSum;
}
//返回三者中的最大值
return max(maxLeftSum,
maxRightSum,
maxLeftBorderSum
+ maxRightBorderSum);
}
long maxSubSum(const
long *a)
{
return maxSumRec(a,
0, a.size()-1);
}
//求出三个long中的最大值
long max(long a, long b, long c)
{
if (a
< b)
{
a
= b;
}
if (a
> c)
return a;
else
return c;
}
4. 时间复杂度为O(n). 此算法是一个线性时间的算法,程序较为简单,但是不容易理解其正确性。简单地说,最大子序列不可能以和为负数的子序列为前缀的。
long maxSubSum(const
long *a)
{
long max =
0, sum = 0;
for (int j
= 0; j < a.size(); j++)
{
sum
+= a[j];
if (sum
> max )
max
= sum;
else if (sum
< 0)
sum
= 0;
}
return max
;
}
相关文章推荐
- 有n个数(两两不同),对于这n个数的每个连续子序列,把其中最大的一个数标记一次,问最后每个数被标记次数
- 最大子序列的3种不同时间复杂度的算法
- 最大子序列和的四种不同复杂度实现
- 最大子序列和的四种不同复杂度实现
- 数据结构与算法分析之最大子序列和
- UVA - 10192 Vacation(dp+最大公共子序列)
- 最大连续子序列和/乘积
- 最大的子序列和问题
- HDU1087 超级跳跃(递增子序列最大和)
- 最大上升子序列(动态规划)
- hdu 1231 最大连续子序列
- HDU 1003 Max Sum 最大连续子序列和
- 最大子数组 三种不同复杂度的算法
- Magical GCD UVA 1642 利用约数个数少来优化 给定n个数,求使连续的一段序列的所有数的最大公约数*数的数量的值最大。输出这个最大值。
- 动态规划:最大连续子序列乘积
- 最大子序列的求解分析(java代码实现)
- 南阳oj742子串和在续(最大m段子序列和+动态规划)
- 每天一道LeetCode-----找到给定序列中所有和为某个值的集合或集合个数,序列中可以有/无重复项,集合元素顺序不同算不同集合等
- 求最大子序列和的两种算法
- 最大连续子序列的线性算法