[演算法]字串左移k位

來源:互聯網
上載者:User

標籤:style   blog   http   color   使用   strong   

如,abcde左移3位為deabc

要求時間複雜度O(n),空間複雜度O(1),每一個字元只能遍曆一次

 

摘自http://blog.csdn.net/geniusluzh/article/details/8460031

利用數學解決該問題

    其實對於這道題,最初一看的想法就是將當前位依次替換左移m位對應的那個位,然後依次替換。後來發現有的情況一次迴圈替換就能全部完成整個串的左移,而有的情況下會出現多個迴圈鏈,一時只得到規律,不能想到很好的證明辦法,只怪以前初等數論沒有好好學啊!

    我們發現對於長度為n的串,左移m位,會形成gcd(n, m)個鏈,這裡的gcd就是大家熟知的最大公約數,每個鏈的長度顯然就是n/(gcd(n, m))。我們如何來證明這個問題呢?我們令i+j*m 和 i+k*m正好走了一圈又指向同一個元素,那麼便是(i+j*m)%n == (i+k*m)%n,因此根據同餘的性質我們知道n | (k-j)*m,而n = n‘ * gcd(n, m), m = m‘ * gcd(n, m)。所以我們得到n‘ | (k-j) * m‘, 由於n‘ 和 m‘ 互素,因此 n‘ | (k - j),因此我們知道最小的k-j = n‘ = n/gcd(n, m),也就是說一個迴圈鏈裡頭有n/gcd(n, m)個元素,因此總共有gcd(n, m)個迴圈鏈,於是得證。因此我們只需要取前gcd(n, m)個元素,每個走一條鏈進行迴圈的替換就行了。其實這個演算法是最優的,真正的O(N)的時間複雜度,而且沒有額外的開銷。

 

int gcd(int m, int n){    if(m < n){        int t = m;        m = n;        n = t;    }    int r = m%n;    while(r){        m = n;        n = r;        r = m%n;            }    return n;} char* leftShift(char* str, int n, int k){    char s, t;    int g = gcd(n,k),len = n / g;    for(int i = 0; i < g; ++i){        s = str[i];        for(int j = 0; j < len; ++j){            t = str[(n - k + i)%n];            str[(n - k + i)%n] = s;            s = t;            i = (n - k + i)%n;                times++;        }            }    return str;}

 


本文基於知識共用署名-非商業性使用 3.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.