• 7、给定n个序列,求相邻的k个数之和为最大


    1、问题描述:给定n个数,求相邻的k个数之和为最大。要求给出复杂度较小的一种算法

    再解决这个问题前,先了解一下类似的常见问题。

    2、给定一串数字(可正可负的int,放在数组Num里),要求找到起始位置start和终止位置end,使得从start位置到end位置的所有数字之和最大,返回这个最大值max

    算法思想:用动态规划算法实现。

    iMaxSum 为以 iNumPar[i] 终止且包含 iNumPar[i] 的最大序列的和,有:

       iMaxSum  =  iNumPar[0];

       iMaxSum  =  iMaxSum > 0 ? iMaxSum + iNumPar[i+1] : iNumPar[i+1];

       其中,i = 0,1,...

    那么和iMaxSum 就是 iNumPar[0] ... iNumPar[n] 中最大的一个序列。

    算法的时间复杂度为O(n)

    示例代码

    #include <iostream>
    
    using namespace std;
    
    void FindTheMaxSum(int iNumPar[], const int iSize, int &ibegin, int &iend, int &iMaxSum)
    {
    	ibegin = iend = 0;
    	int iTemSum = iNumPar[0], iStart = 0;
    	iMaxSum = iTemSum;
    	for (int i = 1; i < iSize; ++i)
    	{
    		if (iTemSum > 0)
    		{
    			iTemSum = iTemSum + iNumPar[i];
    		}
    		else
    		{
    			iTemSum = iNumPar[i];
    			iStart = i;
    		}
    		
    		if (iTemSum > iMaxSum) //更新结果
    		{
    			iMaxSum = iTemSum;
    			ibegin = iStart;
    			iend = i;
    		}
    	}
    }
    
    int main()
    {
        int ibegin = 0, iend = 0, iResult = 0, iCount = 0;
    	int iNum[] = {-1, -2, -3, -4, 0, 1, 2, 3, 4, 5, -20, 40, -3};
    	iCount = sizeof(iNum)/sizeof(iNum[0]);
        FindTheMaxSum(iNum, iCount, ibegin, iend, iResult);
    	cout << ibegin <<" "<< iend <<" "<< iResult <<endl;
    	return 1;
    }
    

    3、最容易想到的就是穷举搜索。在n个序列中求出每k个连续序列的值,进行比较。

    示例代码

    #include <iostream>
    
    using namespace std;
    
    void FindTheMaxKSum(int iNumPar[], const int iSize, int iK, int &ibegin, int &iend, int &iMaxSum)
    {
    //iK指出求最大各子序列的长度
    	int iTemMaxKsum = 0;
    	for (int i = 0; i < iK; ++i)
    	{
    		iTemMaxKsum += iNumPar[i];
    	}
    	iMaxSum = iTemMaxKsum;
    	
    	int iStart = ibegin = 0, iOver = iend = iK - 1;
    	for (int i = 1; (i < iSize) && ((iSize - i) >= iK); ++i)
    	{
    		iTemMaxKsum = 0;
    		for (int j = i; ((j - i) < iK) && (j < iSize); ++j)
    		{
    			iTemMaxKsum += iNumPar[j];
    		}
    
    		if (iTemMaxKsum > iMaxSum)
    		{
    			iMaxSum = iTemMaxKsum;
    			ibegin = i;
    			iend = i + iK - 1;
    		}
    	}
    }
    
    int main()
    {
        int ibegin = 0, iend = 0, iResult = 0, iCount = 0;
    	int iNum[] = {-1, -2, 4, 5, 6, 1, 2, 3, 4, -4, -20, 40, -3};
    	iCount = sizeof(iNum)/sizeof(iNum[0]);
        FindTheMaxKSum(iNum, iCount, 3, ibegin, iend, iResult);
    	cout << ibegin <<" "<< iend <<" "<< iResult <<endl;
    	return 1;
    }
    

    由上可见,复杂度为O(iK + n*k)

    那么有没有更好的方法呢?优化的方法就是把循环体内的相加循环去掉。

    示例代码

    #include <iostream>
    
    using namespace std;
    
    void FindTheMaxKSum(int iNumPar[], const int iSize, int iK, int &ibegin, int &iend, int &iMaxSum)
    {
    //iK指出求最大各子序列的长度
    
    	int *pTempSum = new int[iSize];
    	pTempSum[0] = iNumPar[0];
    	for (int i = 1; i < iSize; i++)
    	{
    		pTempSum[i] = pTempSum[i - 1] + iNumPar[i]; 
    	}
    	
    	int iStart = ibegin = 0;
    	ibegin = 0;
    	iend = iK - 1;
    	iMaxSum = pTempSum[iend];
    
    	for (int i = 1, j = iK; j < iSize; ++i, ++j)
    	{
    		if ((pTempSum[j] - pTempSum[i - 1]) > iMaxSum)
    		{
    			iMaxSum = pTempSum[j] - pTempSum[i - 1];
    			ibegin = i;
    			iend = j;
    		}
    	}
    delete pTempSum[];
    }
    
    int main()
    {
        int ibegin = 0, iend = 0, iResult = 0, iCount = 0;
    	int iNum[] = {-1, -2, 4, 5, 6, 1, 2, 3, 4, -4, -20, 40, -3};
    	iCount = sizeof(iNum)/sizeof(iNum[0]);
        FindTheMaxKSum(iNum, iCount, 3, ibegin, iend, iResult);
    	cout << ibegin <<" "<< iend <<" "<< iResult <<endl;
    	return 1;
    }
    

        由上可见,程序复杂度为O(n)n为问题规模。

    参考

    [1]更多的数学说明:

    http://www.cnblogs.com/Jason_Yao/archive/2009/09/27/1574713.html

    [2]CSDN论坛中的讨论

    http://topic.csdn.net/u/20110402/12/795e568e-b590-4fb0-8a4d-dba8b408441f.html?1021658511

  • 相关阅读:
    ssh中Hibernate懒加载,session问题的学习与理解
    ligerUI---ListBox(列表框可移动)
    ligerUI---下拉菜单(menubar)动态显示(从后台获取数据)
    ligerUI---下拉框(Combobox)
    ligerUI---ligerGrid中treegrid(表格树)的使用
    Hibernate--使用xml配置映射关系
    Hibernate--使用注解配置映射关系
    ligerUI---ligerGrid默认选中checkbox
    ligerUI---ligerGrid分页排序的使用(从后台获取数据显示)
    手机屏幕尺寸与iOS开发坐标的关系
  • 原文地址:https://www.cnblogs.com/mydomain/p/2003320.html
Copyright © 2020-2023  润新知