• 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)的时间内解决问题,这个就留给下次作业了。

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

  • 相关阅读:
    lr 增强窗格中,如何生成调试信息?
    lr 自带的例子,如何进行关联,通过代码的函数进行实现
    lr11 录制脚本时候,无法自动启动ie,查了网上很多方法都未解决?
    loadrunner11 录制脚步不成功,在录制概要出现“No Events were detected”,浮动窗口总是显示“0 Events”,解决办法
    loadrunner11 安装及破解教程来自百度文库
    安装loadrunner11 ,出现如下错误如何解决?
    回收站数据删除了,如何进行恢复?
    网管工作方面——————打印机删除了然后开机重启他依然存在,如何解决
    Windows 不能在 本地计算机 启动 SQL Server 服务 错误代码126
    Sorry, the page you are looking for is currently unavailable. Please try again later. Nginx
  • 原文地址:https://www.cnblogs.com/caoyingjie/p/3329813.html
Copyright © 2020-2023  润新知