• 最大自序和问题


    最大自序和问题。给出一个长度为n的序列


    求最大连续和。换句话说,要求找到1<=i<=j<=n,使得


    尽量大。

    使用枚举,demo1

    	tot = 0;
    	best = A[i];
    	for (int i = 1; i <= n; i++) {
    		for (int j = i; j <= n; j++) { // 检查连续子序列A[i]~A[j]
    			int sum = 0;
    			for (int k = i; k <= j; k++) {
    				sum += A[k];
    				tot++;
    			}
    			if (sum > best) {
    				best = sum; // 更新最大值
    			}
    		}
    	}

    显然有



    优化:设


    直观含义是连续子序列之和等于两个前缀和之差。用这个结论,省略最内层的循环。

    demo2

    	S[0] = 0;
    	for (int i = 1; i <= n; i++) {
    		S[i] = s[i - 1] + A[i]; // 递推前缀和S
    	}
    	for (int i = 1; i <= n; i++) {
    		for (int j = i; j <= n; j++) {
    			best = max(best, S[j] - S[i - 1]); // 更新最大值
    		}
    	}

    此时时间复杂度为O(n^2)。


    下面用分治法:

    demo3

    int maxSubSum(int* A, int x, int y) // 返回数组在左闭右开区间[x,y)中的最大连续和
    {
    	if (y - x == 1) {
    		return A[x]; // 只有一个元素,直接返回
    	}
    	int m = x + (y - x) / 2; // 分治第一步:划分成[x,m)和[m,y)
    	int maxs = max(maxSubSum(A, x, m), maxSubSum(A, m, y)); // 分治第二步:递归求解
    	int v, L, R;
    	v = 0; L = A[m - 1]; // 分治第三步:合并(1),从分界点开始往左的最大连续和L
    	for (int i = m - 1; i >= x; i--) {
    		L = max(L, v += A[i]);
    	}
    	v = 0; R = A[m]; // 分治第三步:合并(2),从分界点开始往右的最大连续和R
    	for (int i = m; i < y; i++) {
    		R = max(R, v += A[i]);
    	}
    	return max(maxs, L + R); // 把子问题的解与L和R比较
    }
    上述方法有



    最后如果给问题加一个条件,为方便起见,如果所有整数均为负数,则最大子序和为0.

    这里给出上述假设下的联机算法:

    int maxSubsequenceSum(const int A[], int N)
    {
    	int thisSum, maxSum, j;
    
    	thisSum = maxSum = 0;
    	for (int j = 0; j < N; j++) {
    		thisSum += A[j];
    		if (thisSum > maxSum) {
    			maxSum = thisSum;
    		}
    		else if (thisSum < 0) {
    			thisSum = 0;
    		}
    	}
    	return maxSum;
    }

    这个算法附带的优点是,它只对数据进行一次扫描,一旦A[i]被读入并处理,它就不再需要被记忆。因此,如果数组在磁盘或磁带上,它就可以被顺序读入,在主存中不需要存储数组的任何部分。不仅如此,在任意时刻,算法都能对它已经读入的数据给出子序列问题的正确答案(其他算法不具有这个特性)。具有这种特性的算法叫做联机算法(online algorithm)。仅需要常量空间并以线性时间运行的联机算法几乎是完美的算法。


  • 相关阅读:
    C++头文件,预处理详解
    在VS2013中查看C/C++预处理后的文件
    使用apache.lang包安全简洁地操作Java时间
    FileInputStream 和 FileOutputStream
    【转】彻底搞清计算结构体大小和数据对齐原则
    NDK学习笔记-gdb调试
    NDK学习笔记-gdb调试
    NDK学习笔记-多线程与生产消费模式
    NDK学习笔记-多线程与生产消费模式
    Android-Makefile
  • 原文地址:https://www.cnblogs.com/zhangyaoqi/p/4591532.html
Copyright © 2020-2023  润新知