主要有几个衡量的指标:

  • 时间复杂度:主要有
  • 空间复杂度:有些排序算法需要额外的辅助空间,而有些则能实现“原地排序”;
  • 稳定性:相同的元素在排序之前和排序之后相对位置是否有可能发生变化;
  • 适用条件:算法是否有些额外的限制条件

在我的见解中,整数的线性排序,就需要一个hash计数数组就行,效率很高。缺点就是额外空间。

基数排序:应对数值很大的情况。“越重要的越在后面比较”。缺点是不呈现时空局部性,因为在按位对每个数进行排序的过程中,一个数的位置可能发生巨大的变化,所以不能充分利用现代机器缓存提供的优势。

 

求子数组最大和问题:

1.暴力枚举:

int maxSubArray(int *A,int n)  
{  
    int maxium = -INF;       //保存最大子数组之和  
    for i=0 to n-1 do  
        sum = 0;          //sum记录第i到j的元素之和  
        for j=i to n-1 do  
            sum += A[j];  
            if sum>maxium do      //更新最大值  
                maxium = sum;  
    return maxium;  
}  

复杂度为O(n2)。

2.分支界定法

复杂度为O(nlogn),如果把组分为一半,最大和可能在左子组或者右子组,或跨组(从中线向左向右找max求和)。

int maxSubArray(int *A,int l,int r)  
{  
    if l<r do  
        mid = (l+r)/2;  
        ml = maxSubArray(A,l,mid);        //分治  
        mr = maxSubArray(A,mid+1,r);  
        for i=mid downto l do  
            search maxleft;  
        for i=mid+1 to r do   
            search maxright;  
        return max(ml,mr,maxleft+maxright);     //归并  
    then      //递归出口  
        return A[l];   
}  

3.动态规划

int maxSubArray(int *A,int n)  
{  
    cursum = A[0];  
    maxsum = A[0];  
    for i=1 to n-1 do  
 /*当我们加上一个正数时,和会增加;当我们加上一个负数时,和会减少。如果当前得到的和是个负数,那么这个和在接下来的累加中应该抛弃并重新清零,不然的话这个负数将会减少接下来的和。*/  
        if cursum<0 do     
            cursum = 0;  
        cursum += A[i];  
        if cursum>maxsum do  
            maxsum = cursum;  
    return maxsum;  
}  
复杂度只是O(n),必要扩展还可以记录最大和子组的起始终止位置。