#数据结构与算法学习笔记#剑指Offer28:连续子数组最大和 + 分治算法/动态规划 + 测试用例(Java、C/C++)

版权声明:本文为博主NJU_ChopinXBP原创文章,发表于CSDN,仅供交流学习使用,转载请私信或评论联系,未经博主允许不得转载。感谢您的评论与点赞。 https://blog.csdn.net/qq_20304723/article/details/82843667

2018.9.25

前面一段时间参加了研究生数学建模大赛。比赛完又考了一个托业。感觉数学英语功底得到了很大提升,同时也断更了两周。总算在中秋节第二天正式回归了。

回归第一题看得真是感慨万分。这题是我刚刚入门数据结构与算法的时候做的第一道大题,解法至今记忆犹新。能够实现的算法有两种:

方法一:动态规划/在线处理算法,o(n)。设定一个积累值和一个结果值,从左向右不断累加,当积累值大于结果值的时候更新结果,当积累结果为负数的时候抛弃之前积累的结果。既然刚刚从数学建模大赛回来,那就摆个动态规划的模型吧。

本题的动态规划模型:

 f(i) = \left\{\begin{matrix} pData[i] &&i = 0 &or& f(i-1)\leq0 \\ f(i-1) + pData[i] &&i\neq 0 &or& f(i-1)> 0 \end{matrix}\right.

之前写过的代码:#数据结构与算法学习笔记#PTA3:在线处理算法求最大子列和,并返回最大子列和头尾元素(C/C++)(2004年浙大计科考研复试)

方法二:分治算法,o(logn)。基本思想是递归,把每一次递归看成三部分:对每个序列二分,左边子序列、右边子序列、跨中线子序列分别求最大子列和,挑选最大的子列和进行返回。递归找到最大子列和。

之前写过的代码:#数据结构与算法学习笔记#PTA4:分治算法求最大子列和(C/C++)


题目描述

HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)


之前两篇文章都是在3月份的时候写的,如果要说这半年来有什么成长的话,那应该是现在开始会有意识地优化代码的效率和可读性了吧。

Java实现(方法一):

/**
 * 
 * @author ChopinXBP 
 * 给一个数组,返回它的最大连续子序列的和。
 *
 */

public class FindGreatestSumOfSubArray_29 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] array = {6,-3,-2,7,-15,1,2,2};
		System.out.println(FindGreatestSumOfSubArray(array));
	}
	
	//动态规划/在线处理算法
    public static int FindGreatestSumOfSubArray(int[] array) {
    	if(array == null)return 0;
    	if(array.length == 0)return array[0];
    	
        int max = array[0];			//积累值
        int result = array[0];		//最终结果
        for(int i = 1; i < array.length; i++){
        	max += array[i];
        	if(max > result) result = max;	//当积累值大于结果值则更新结果
        	if(max < 0) max = 0;			//当和为负数抛弃之前积累结果
        }
        return result;
    }

}

C++实现(方法一):

bool g_InvalidInput = false;

int FindGreatestSumOfSubArray(int *pData, int nLength)
{
    if((pData == NULL) || (nLength <= 0))
    {
        g_InvalidInput = true;
        return 0;
    }

    g_InvalidInput = false;

    int nCurSum = 0;
    int nGreatestSum = 0x80000000;
    for(int i = 0; i < nLength; ++i)
    {
        if(nCurSum <= 0)
            nCurSum = pData[i];
        else
            nCurSum += pData[i];

        if(nCurSum > nGreatestSum)
            nGreatestSum = nCurSum;
    }

    return nGreatestSum;
} 

测试代码:

// ====================测试代码====================
void Test(char* testName, int* pData, int nLength, int expected, bool expectedFlag)
{
    if(testName != NULL)
        printf("%s begins: \n", testName);

    int result = FindGreatestSumOfSubArray(pData, nLength);
    if(result == expected && expectedFlag == g_InvalidInput)
        printf("Passed.\n");
    else
        printf("Failed.\n");
}

// 1, -2, 3, 10, -4, 7, 2, -5
void Test1()
{
    int data[] = {1, -2, 3, 10, -4, 7, 2, -5};
    Test("Test1", data, sizeof(data) / sizeof(int), 18, false);
}

// 所有数字都是负数
// -2, -8, -1, -5, -9
void Test2()
{
    int data[] = {-2, -8, -1, -5, -9};
    Test("Test2", data, sizeof(data) / sizeof(int), -1, false);
}

// 所有数字都是正数
// 2, 8, 1, 5, 9
void Test3()
{
    int data[] = {2, 8, 1, 5, 9};
    Test("Test3", data, sizeof(data) / sizeof(int), 25, false);
}

// 无效输入
void Test4()
{
    Test("Test4", NULL, 0, 0, true);
}

int _tmain(int argc, _TCHAR* argv[])
{
    Test1();
    Test2();
    Test3();
    Test4();

    return 0;
}

#Coding一小时,Copying一秒钟。留个言点个赞呗,谢谢你#

猜你喜欢

转载自blog.csdn.net/qq_20304723/article/details/82843667