zoukankan      html  css  js  c++  java
  • homework-01

      最大子数组和问题求解:

      对于这个问题,一下就可以想到一个O(n2)的算法,即穷举连续数组段的首尾索引,两个for解决问题。但还有没有更快的方法呢?答案是肯定的,下面就给出一个时间复杂度为O(n)的算法。

       该算法是基于动态规划思想的,我们考虑数组(arr[])中以 i 为结尾的连续数据的的最大值,并用max_arr[]来记录这个最大值。显然,对于 i=0,最大值就是arr[0],即max_arr[0]=arr[0],那对于 i>0 的情况呢?显然max_arr[i]的值受到max_arr[i-1]的值的影响(这正是动态规划思想的体现:将之前计算的结果保留下来用以计算之后的结 果),如果max_arr[i-1]>0(等不等于0无所谓,看具体要求),则max_arr[i]=max_arr[i-1]+arr[i],否 则max_arr[i]=arr[i],除了这两种情况别无其他。于是我们得到了下面这个递推关系:

                                            max_arr[i]= arr[i],i=0或max_arr[i-1]>=0

                                                              max_arr[i-1]+arr[i],其他情况

    根 据该递推关系,我们就可以得到最大的子数组和了,但还有一个小问题:这样我们只能的到最终的结果值,却不能的到相应的子数组,那有没有办法将子数组也找出 来呢?显然是可以的。我们可以在申请一个数组来保存以 i 结尾的子数组取得最大值时最开始的索引(相对于原数组),而不难得出该数组(max_startindex_arr)满足以下递推关系:

                                         max_startindex_arr=0,i=0

                                                                        max_startindex_arr[i]=max_startindex_arr[i-1],max_arr[i-1]>=0

                                                                        max_startindex_arr[i]=i,其他情况

      这样我们便记录了所有所需的信息,问题便迎刃而解了,当然这里的最大子数组不唯一,可能有多个,不过根据上面记录的信息,我们都可以把他们找出来。下面给出一种C++实现:

    平台:WindowsVisual Studio

    语言:C++

    输入:保存在文件中,第一行是一个数字N加一个英文逗号",",表征输入数据的个数;第二行有N个数字,以英文

              逗号隔开,作为输入的原始数组。

    输入样例:6,
                      5,6,-3,8,-9,2

    输出:输出到屏幕,格式如下:

               最大值:16
               首次出现范围:0 -- 3

               其中,最大值是最大子数组和,首次出现范围是产生第一个最大值的子数组索引范围。

    运行方法:在cmd中运行:程序可执行文件名+存放输入数据的文件全路径或相对路径。

    测试用例:

    输出结果:

    源代码:

    //下面程序针对一维数组一维数组
    #include<iostream>
    #include<fstream>
    using namespace std;
    
    int find_max(int *src_arr,int *max_arr,int *max_startindex_arr,int len){
        int max_index=0;
        for (int i = 1; i < len; i++)
        {
            if (max_arr[i-1]>=0)
            {
                max_arr[i]=max_arr[i-1]+src_arr[i];
                max_startindex_arr[i]=max_startindex_arr[i-1];
                if (max_arr[i]>max_arr[max_index])
                {
                    max_index=i;
                }
            }else
            {
                max_arr[i]=src_arr[i];
                max_startindex_arr[i]=i;
                if (max_arr[i]>max_arr[max_index])
                {
                    max_index=i;
                }
            }
        }
        return max_index;
    }
    int main(int argc,char *argv[]){
        int element_num=-1;                //数组元素个数
        int max_index=0;                         //最大值索引
        char tmp;
        ifstream my_cin;
        int *src_arr;                      //输入数据数组
        int *max_arr;                      //保存当前最大值的数组
        int *max_startindex_arr;           //保存最大值范围的起始索引
        if(argc!=2){
            cout<<"命令行格式错误!";
            return 0;
        }else{
            my_cin.open(argv[1]);
        }
        if(!my_cin.is_open()){
            cout<<"打开输入文件失败!";
            return 0;
        }else{
            if(!(my_cin >> element_num)){
                cout<<"文件格式错误,无法确定输入数据个数!";
                my_cin.close();
                return 0;
            }
            if(element_num==0){
                cout<<"原始数据个数为0!";
                my_cin.close();
                return 0;
            }
            src_arr = new int[element_num];
            max_arr = new int[element_num];
            max_startindex_arr = new int[element_num];
    
            for (int i = 0; i < element_num; i++)
            {
                my_cin>>tmp;
                if (tmp!=','||!(my_cin>>src_arr[i]))
                {
                    cout<<"文件格式错误!";
                    my_cin.close();
                    return 0;
                }
            }
            my_cin.close();
            max_arr[0]=src_arr[0];
            max_startindex_arr[0]=0;
        }
    
        max_index = find_max(src_arr,max_arr,max_startindex_arr,element_num);
    
        cout<<"最大值:"<<max_arr[max_index]<<endl;
        cout<<"首次出现范围:"<<max_startindex_arr[max_index]<<" -- "<<max_index<<endl;
    
        return 0;
    }

      从上面的代码可以看出:其实核心代码没有几行,大量的代码都是一些容错性处理。当然,可能还是有许多错误不能处理,就比如结果溢出,这些准备在下一次作业中进行处理。当然,要想支持任意大整数,如果不利用语言特性(如python、java对任意大数据的支持),恐怕还是有点难度的。另外,由一维数组的求解过程,我们也很容易联想到二维数组的求解算法,可以在O(mn)的时间内解决问题,这个就留给下次作业了。

    另外:我所使用的教科书是《代码大全》。

  • 相关阅读:
    mysql 远程登陆不上
    hdu 5339 Untitled【搜索】
    SqlServer 书目
    passwordauthentication yes
    oracle 11g RAC ocfs2
    Oracle 11g RAC database on ASM, ACFS or OCFS2
    CentOS ips bonding
    Oracle 11g RAC features
    openStack 王者归来之 trivial matters
    openstack windows 2008 img
  • 原文地址:https://www.cnblogs.com/caoyingjie/p/3329813.html
Copyright © 2011-2022 走看看