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

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

  • 相关阅读:
    UITextView自适应高度解决方法
    UITextView自适应高度出现的问题
    UITextView出现的一些问题
    服务器终于好了!
    Update语句
    VS.NET经验与技巧
    唯一约束
    由C#风潮想起的-给初学编程者的忠告
    location.search在客户端获取Url参数的方法
    Web Services 入门概念
  • 原文地址:https://www.cnblogs.com/caoyingjie/p/3329813.html
Copyright © 2011-2022 走看看