您的位置:首页 > 其它

最大自序列和问题的求解

2018-01-12 16:32 288 查看

问题:



求解

讨论四种算法的运行时间。




算法1 O(N3):

public static int method1(int[] a){
int max=0;
for(int i =0;i<a.length;i++){
for(int j =i;j<a.length;j++){
int temp=0;
for(int k=i;k<=j;k++){
temp+=a[k];
}
if(temp>max){
max=temp;
}
}
}
return max;
}


算法2 O(N2)

public static int method2(int[] a) {
int max = 0;
for (int i = 0; i < a.length; i++) {
int temp = 0;
for (int j = i; j < a.length; j++) {
temp += a[j];
if (temp > max) {
max = temp;
}
}
}
return max;
}


算法1和算法2实现思路是一样,从A1开始往后取值计算子列和,当取值取到最后一位数时为一次循环结束,然后从A2开始取值计算。

算法1比算法2复杂的是计算部分过量消耗,算法2改良之后在求索引为k的temp时可以使用索引为k-1的temp+Ak。

算法3 O(NlogN)

int MaxSubSeqSum(int arr[], int left, int right) {
if (left == right) {
if (arr[left] > 0) {
return arr[left];
} else {
return 0;
}
}
int center = (left + right) / 2;
int leftMaxSum = MaxSubSeqSum(arr, left, center); /* 分界线左侧最大子数列 */
int rigthMaxSum = MaxSubSeqSum(arr, center + 1, right); /* 分界线右侧最大子数列 */

/* 以分界线往左求最大子数列 */
int leftBorderSum = 0, maxLeftBorderSum = 0;
for (int i = center; i >= left; i--) {
leftBorderSum += arr[i];
if (leftBorderSum > maxLeftBorderSum) {
maxLeftBorderSum = leftBorderSum;
}
}

/* 以分界线往右求最大子数列 */
int rightBorderSum = 0, maxRightBorderSum = 0;
for (int j = center + 1; j <= right; j++) {
rightBorderSum += arr[j];
if (rightBorderSum > maxRightBorderSum) {
maxRightBorderSum = rightBorderSum;
}
}
/* 跨越分界线最大子数列和 */
int maxBorderSum = maxLeftBorderSum + maxRightBorderSum;

return maxSum(leftMaxSum, rigthMaxSum, maxBorderSum);
}


算法三采用分治策略,其想法是把问题分成2个大致相等的问题,然后递归地对它们求解,这是“分”的部分。“治”阶段将2个子问题的解修补到一起并可能再做些少量的附加工作,最后得到整个问题的解。

算法4 O(N)

public static int method4(int[] a) {
int max = 0;
int temp = 0;
for (int i = 0; i < a.length; i++) {
temp+=a[i];
if (temp > max) {
max = temp;
}
if(temp<0){
temp=0;
}
}
return max;
}


算法4对算法2再进行改进。通过分析得出一个结论,如果a[i]是负数,那么它不可能是最大值序列的起点。近似的,任何负子列都不是最大值序列的前缀。如果a[i]到a[j]的子序列是负的,那么我们可以直接推进到j+1。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: