任意自然數分解為連續自然數和問題

來源:互聯網
上載者:User

 

          前天,得知一個朋友去了網易應聘,只是在筆試中遇到幾個比較麻煩的演算法問題(主要是在考試限時內有難度),告訴我們幾個相熟的共同探討,任意自然數N分解為連續自然數和問題就是其中之一。這個問題很容易就能得到其長為k+1的序列和必然有等於0~k之和加上k+1個m的規律,但是要想得到高效的演算法就必須先找到一個理想的邊界條件,這樣才能有效減少不必要的尋找,一旦邊界不對則得不到完整正確的解。一開始我總想直接求出最長序列以便得到其長度,然而實在是數學功底差,不得不求其次另找了個差一些的條件,這個條件就是:噹噹前序列的長度k對應的0~k之和大於該自然數N時,測試終止。這個原理很容易理解吧?

以下就是代碼:

#include <iostream>
#include <cmath>

using std::cout;
using std::cin;
using std::endl;

int main(void)
...{
    int N = 0;
    cout<<"請輸入N: ";
    while(!(cin>>N))
    ...{    
        cout<<"input fail,please retry!"<<endl;
        cout<<"請輸入N: ";
        cin.clear();
    }
    int k = 0;
    int m = N;
    int i = 0;
    int big,small,pre_i;//這裡的幾個變數不過十位了讓代碼的含義更清晰,其實完全可以省略.
    int j = 0;               //這個主要是為了測試和分析方便,也不是必要的.
    do
    ...{
        pre_i = k = k+i;
        m = (N-k)/(i+1);
        if(N == m*(i+1)+k)
        ...{
            big = m+i;
            small = m;
            ++j;
            cout<<"circle ["<<i+1<<"];  from  "<<small<<"  to  "<<big<<endl;
        }
        ++i;
    }while(N>pre_i+1);//如果N<pre_i(前i項和),說明達到最長序列
    cout<<"circles["<<i<<"]  total "<<j<<endl;
    system("pause");
    return 0;
}

 

下面是測試1:

可以看出,就這個數字來說,複雜度相差很小,近乎理想。那麼再試試另一個:

看看,和理想的640次迴圈相比多了將近一倍。然而這個差距並非單調遞增的。

不過效率還是可以的,在我的酷睿E6300機器上可以說一閃而過,主要是輸出操作佔用了比較長的時間。

 

        然而。。。。。當N接近資料類型上限時,溢出問題太嚴重了,補救方法是將while迴圈條件中的資料強制轉換成無符號以提高資料上限。儘管數學理論沒有錯,但是顯然不適合電腦實現。這讓我想起有人認為,研究演算法的可以完全不會寫代碼,甚至不瞭解電腦原理,這可能嗎?就像上面這個演算法,理論上有錯嗎?然而實際條件給限制了。不理解資料怎麼溢出,就不能提前預見這種錯誤,那麼費了半天神想出的演算法只能是空談。

        而另一重解決方案是預估計序列的最大長度,再用這個長度作為迴圈結束條件,經分析,最大長度應該為:

                      int maxLength = pow(N* 2.0,0.5) + 1;

從而程式修改如下:

#include <iostream>
#include <cmath>
using std::cout;
using std::cin;
using std::endl;
int main(void)
...{
    int N = 0;
    cout<<"請輸入N: ";
    while(!(cin>>N))
    ...{    
        cout<<"input fail,please retry!"<<endl;
        cout<<"請輸入N: ";
        cin.clear();
    }
    int k = 0;
    int m = N;
    int i = 0;
    int big,small,pre_m;//這裡的幾個變數不過十位了讓代碼的含義更清晰,其實完全可以省略.
    int j = 0;          //這個主要是為了測試和分析方便,也不是必要的.
    int maxLength = pow(N* 2.0,0.5) + 1;//這是我們估計的最長序列長度。
//  int maxLength = log((double)N);
    cout<<"maxLength = "<<maxLength<<endl;
    do
    ...{
        k = k+i;
//      pre_m =k;
        m = (N-k)/(i+1);
        if(N == m*(i+1)+k)
        ...{
            big = m+i;
            small = m;
            ++j;
            cout<<"circle ["<<i+1<<"];  from  "<<small<<"  to  "<<big<<endl;
        }
        ++i;
//  }while((unsigned)N>(unsigned)pre_m);//如果N<pre_i(前i項和),說明達到最長序列
    }while(i<maxLength);
    cout<<"circles["<<i<<"]  total "<<j<<endl;
    system("pause");
    return 0;
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.