1. 程式人生 > >程式設計珠璣第八章,最接近0的的子向量

程式設計珠璣第八章,最接近0的的子向量

看了程式設計珠璣第八章中的內容,後面的課後練習也是非常的有意思,有一題是這麼說的,給定整數m和整數n和實數向量x[n],

請找出使總和x[i]+……+x[i+m]最接近0的整數i。

我這裡先不說明怎麼獲取最接近0的i,我先說明如何獲得與0最接近的子陣列之和。

看了寫網上有些人已經多出了一些解法,但是覺得它們的做法好像都有些問題。例如這位大神的做法就是有些問題的。

int approximate(int * pArry, int len)  
{  
    int * cum = 0;  
    int * realarry = new int[len + 1];  
    realarry[0] = 0;    
    cum = realarry + 1;  //cum[-1] = 0  
  
    //累計pArry[0....i]的和存放於cum[i]中  
    for (int i = 0; i < len; i++)  
    {  
        cum[i] = cum[i - 1] + pArry[i];  
    }  
    sort(cum, cum + len); //對cum排序  
    int iMin = cum[1] - cum[0];  
    for (int k = 1; k < len; k++)  
    {  
        iMin = min(iMin, cum[k] - cum[k - 1]);  //返回相鄰兩個元素差值最小的  
    }  
    return iMin;  
}  

式子中的cum[i]代表的是從第一個元素到該元素的累加和,如果cum[l-1] = cum[n],那麼cum[l..n]就是最接近0子向量,這裡一定是0.但是,最接近0的子向量也很差不多,只要把所有的cum排序就是了,delta最小的就是了,整個演算法複雜度就是排序了。他的程式碼中沒有考慮cum[i] 直接為0的情況,顯然這時候的意思是從陣列的開始到該元素的累加和就是0。

他的程式碼對於這個example是會出錯的[-1,-1,2,1,2]

其實只需要新增一行程式碼就可以了。

int approximate(int * pArry, int len)
    {
        int * cum = 0;
        int * realarry = new int[len + 1];
        realarry[0] = 0;
        cum = realarry + 1;  //cum[-1] = 0
        
        //累計pArry[0....i]的和存放於cum[i]中
        for (int i = 0; i < len; i++)
        {
            cum[i] = cum[i - 1] + pArry[i];
            if(cum[i]==0)
                return 0;
        }
        sort(cum, cum + len); //對cum排序
        int iMin = cum[1] - cum[0];
        for (int k = 1; k < len; k++)
        {
            iMin = min(iMin, cum[k] - cum[k - 1]);  //返回相鄰兩個元素差值最小的
        }  
        return iMin;  
    }