DSAA之最大子序列之和问题(四)

原创 2018年04月17日 18:30:36

1. 算法4

  该算法比较巧妙,先从一个角度出发:最大子序列首位元素不能小于0,然后扩展概念:最大子序列前几项之和不应该小于0,根据这个准则并不能写出该算法,还要牢记子序列元素的index是从左至右,或者说从小到大。
  根据以上几点,如果我们不玩后验逻辑,(根据结果去理解过程)此时我们写这个程序应该是抱着找到最大子序列头几项之和不小于0的想法。修改maxsubsquencesum如下:

int maxsubsquencesum(int * ptr,int n){
    int i,j,k,thissum,topsquencemaxsum=0;
    thissum=0;
    for(i=0;i<n;i++){

        thissum+=*(ptr+i);
            if(thissum > 0)
                topsquencemaxsum=thisum;
        //直接舍弃前面和小于0的几项
        else if(thissum <0)
            thissum=0;
    }
    return topsquencemaxsum;
}

  很显然该算法的时间复杂度为O(n),特别的上面该算法的实现只能解最大子序列之和大于0的情况。
  

2. Logarithms in the Running Time

  两个估计算法运行时间的准则:

  • An algorithm is O(logn) if it takes constant (O(1)) time to cut the problem size by a fraction (which is usually 1/2 ).
  • On the other hand, if constant time is required to merely reduce the problem by a constant amount (such as to make the problem smaller by 1), then the algorithm is O(n).

  对分查找和二叉树查找很像,假设数列已经按照顺序排列,寻找一个元素是否位于该数列中,其算法时间复杂度为O(logn),和《DSAA》不同一种递归的实现思路如下:

char binarysearch(int * ptr, int x, int start, int end){
     int center;
     //基准
     if(start == end)
         if(*(ptr+start) == x)
             return x;
         else 
             return 'a';
     //递进基准
     center=(start + end)/2;
     if(*(ptr+center) > x)
         binarysearch(ptr, x, start, center);
     else if(*(ptr+center) < x)
         binarysearch(ptr, x, center+1, end);
     else
         return x;
}

  结果如下:

[root@localhost ~]# ./2_2           
5
1 2 3 4 5
please input your goal:
1
find 1
[root@localhost ~]# ./2_2
5
1 2 3 4 5
please input your goal:
0
can't find 0
[root@localhost ~]# 

  每次递归的执行语句运行时间为O(1),运行次数f2f=n,变换得到f=log2n=logn,故该算法的复杂度为T(n)=O(logn1)=O(logn)

2.2 Euclid’s algorithm

  欧几里德算法为什么是正确的证明,笔者就直接略过,直接记结论,两个数的最大公约数可以如下所示的求解,同样区别于《DSAA》,用递归的思路:


int gcd(int x, int y){
   int current_gcd;
   static int pre_gcd;
   //此时在基准之前进行执行该语句
   current_gcd=x%y;
   if(current_gcd == 0)
        return pre_gcd;
   pre_gcd=current_gcd;
   gcd(y,current_gcd);
}

  结果:

[root@localhost data_struce]# ./2_3
50 15
gcd: 5
[root@localhost data_struce]# ./2_3
1989 1590
gcd: 3
[root@localhost data_struce]# 

  在时间复杂度方面,根据:

THEOREM 2.1.
If m > n, then m mod n < m/2.

  该定理的证明比较简单不赘述,根据该定理,可以假设上面的递归最多执行logn次,当然并不准确,并且远远扩大了递归次数,所以最坏的运行时间小于O(logn)

2.3 Exponentiation

  一般提到取幂运算,直接会想到时间复杂度为O(n)的常规思路,但是如果按照次数拆分,我们最多需要logn次乘法,显然领先前面的常规思路:

int power(int x, int n){
    if( n == 0)
        return 1;
    if(IsEven(n))
        return power(x*x,n/2);
        else
            return power(x*x,n/2)*x;        
} 

  《DSAA》还提出了一种错误的写法:

int power(int x, int n){
    if( n == 0)
        return 1;
    if(IsEven(n))
            return power(x,n/2)*power(x,n/2);
    else
            return power(x*x,n/2)*x;        
} 

  该写法的时间复杂度将不是O(logn),可以从乘法次数分析,递归的次数将增加很多,具体分析比较麻烦,可以稍微思考下return power(x,n/2)*power(x,n/2)每次调用都将多产生一个时间复杂度为O(log(n/2))的子问题。

3. 最后

  还是很有意思,起码比较烧脑,如果笔者以前是计科专业,必然走向ACM的道路,还是蛮喜欢的。

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LoveStackover/article/details/79978867

DSAA之最大子序列之和问题(二)

最大子序列之和的几种算法   首先必须强调,笔者使用《DSAA》英文版有大量印刷错误,导致笔者浪费很多时间。所以建议对有疑惑的地方与别的版本对照。 1. 算法1   常规解法,也就是穷举法:...
  • LoveStackover
  • LoveStackover
  • 2018-04-16 09:23:46
  • 18

DSAA之最大子序列之和问题(三)

1. 算法3   这也是笔者第一次接触divide and conquer思想,但是《DSAA》的描述不够容易理解: The last case can be obtained by fin...
  • LoveStackover
  • LoveStackover
  • 2018-04-16 22:06:52
  • 3

最大子序列和的线性时间解法

最大子序列和的一个线性时间解法及解释。
  • wenwuchige
  • wenwuchige
  • 2015-03-12 14:57:44
  • 632

求最大子序列之和的四种方法

四种求最大子序列和的方法,效率一个比一个高。 方法二是方法一的改进 方法三是采用分治的思想,编写递归函数 方法四 最为巧妙,代码少,效率高,逻辑清晰 对原书中的代码做了一小点...
  • aa8568849
  • aa8568849
  • 2016-09-22 15:44:13
  • 418

求最大子序列和及其位置(四种经典方法)

算法部分 #include #include using namespace std; //http://blog.163.com/kevinlee_2010/blog/static/16982...
  • gukesdo
  • gukesdo
  • 2012-04-18 09:31:42
  • 3570

求最大子序列之和问题

问题描述                 给定一组整数序列,求出这组序列和中的最大值,不要求求出最大的子序列。                 例如:                  ...
  • Heavy_Dream
  • Heavy_Dream
  • 2017-09-09 21:17:10
  • 134

最大子序列之和问题

最大子序列之和问题 这个问题非常有趣,因为有很多中算法可以解决这个问题。而这些算法的执行效率也多种多样。下面我们将看到四种算法,算法复杂度从指数一直过渡到线性复杂度。充分体现了算法的优劣对执行效率的影...
  • fallStones
  • fallStones
  • 2009-05-27 00:30:00
  • 2184

最大连续子序列 及 延伸题目

最大连续子序列问题问题定义: 给定K个整数的序列{ N1, N2, …, NK },其任意连续子序列可表示为{ Ni, Ni+1, …, Nj },其中 1 ...
  • rylq56m9
  • rylq56m9
  • 2016-08-28 23:24:55
  • 651

最大子序列之和C++实现常数时间

  • 2012年12月27日 09:56
  • 2KB
  • 下载

最大子序列和的四种算法

1.穷举法算法思想:算出每个子序列的和,即算出序列中第i个到第j个数的和(j&amp;gt;=i),并进行比较算法: public static int maxSubSum1(int[] a) { ...
  • zzl913657644
  • zzl913657644
  • 2016-09-04 13:37:19
  • 7912
收藏助手
不良信息举报
您举报文章:DSAA之最大子序列之和问题(四)
举报原因:
原因补充:

(最多只允许输入30个字)