輾轉相除法(GCD)求左旋轉字元串

来源:http://www.cnblogs.com/huangweiyang/archive/2017/01/18/6297874.html
-Advertisement-
Play Games

今天在牛客網上做了一道題,題意就是求左旋轉字元串。我使用輾轉相除法解之,一次性AC通過。實話說,每次寫演算法一次性通過,甚至一點編譯錯誤都沒有,我覺得這就是對我最好的嘉獎。 題目描述: 彙編語言中有一種移位指令叫做迴圈左移(ROL),現在有個簡單的任務,就是用字元串模擬這個指令的運算結果。對於一個給定 ...


今天在牛客網上做了一道題,題意就是求左旋轉字元串。我使用輾轉相除法解之,一次性AC通過。實話說,每次寫演算法一次性通過,甚至一點編譯錯誤都沒有,我覺得這就是對我最好的嘉獎。

題目描述:
彙編語言中有一種移位指令叫做迴圈左移(ROL),現在有個簡單的任務,就是用字元串模擬這個指令的運算結果。對於一個給定的字元序列S,請你把其迴圈左移K位後的序列輸出。例如,字元序列S=”abcXYZdef”,要求輸出迴圈左移3位後的結果,即“XYZdefabc”。是不是很簡單?OK,搞定它!

這麼多廢話,實際上就是求左旋轉字元串。這裡我先給出我的輾轉相除法代碼:

class Solution {
public:
    string LeftRotateString(string str, int n) {
        int length = str.length();
        if(length <= n)
            return str;
        char *sz = new char[length+1];
        strcpy(sz, str.c_str());
        int times = gcd(length, n);
        while(times--)  //註意這裡先判斷,再--,所以下麵times已經是減過了的
            rotate(sz+times, length, n);
        string res(sz);
        delete []sz;
        return res;
    }
    void rotate(char* sz, int length, int n){
        char* p1 = sz;
        char* p2 = sz + n;
        char tmp = *sz;
        while(p2 != sz){
            *p1 = *p2;
            p1 = p2;
            if(p2 + n > sz + length - 1)
                p2 = sz + (n - ((sz + length) - p2));
            else
                p2 += n;
        }
        *p1 = tmp;
    } 
    int gcd(int m, int n){
        while(n != 0){
            if(m < n)
                std::swap(m, n);
            int tmp = m % n;
            m = n;
            n = tmp;
        }
        return m;
    }
};

思路大致是這樣的:對於一個字元串,先求出GCD,也就是字元串長度和要旋轉個數的最大公約數。這個最大公約數是我們即將要用到的迴圈鏈的數目。也就是執行rotate迴圈的次數。

現在解釋什麼是迴圈鏈。比如“1234”,我們求它把前面3個字元放到後面的情況,即n=3。此時GCD(4,3)=1,即times=1。那麼分析rotate函數。由於在該函數中我們用tmp保存了sz,你需要用tmp保存了這個值,也就是p1的值,我們就可以使用*p2覆蓋該位置的值了,並且p2=p1+n。對於該情況,rotate函數依照代碼執行的流程為(用下劃線表示空位,也就是p1指向的將被覆蓋的位置):

_ 2 3 4 -> 4 2 3 _ -> 4 2 _ 3 -> 4 _ 2 3 -> 4 1 2 3(這是最後一步:*p1=tmp)

如上,這個rotate函數只需執行一次就可以達到目的,旋轉3個字元要求達成。這就叫做一次迴圈鏈,最大公約數times的值就說明瞭這個問題。

再舉一例,有兩個迴圈鏈的例子:還是“1234”,求把前兩個字元放在後面的情況,即n=2。GCD(4,2)=2,可知有兩個迴圈鏈。我們來驗證一下:

第一次:times=1(由於times--),所以p1=2,p2=4(p2=p1+n),所以迴圈流程:

1 _ 3 4 -> 1 4 3 _ -> 1 4 3 2

第二次:times=0,並且p1=1,p2=3,迴圈流程為:

_ 4 3 2 -> 3 4 _ 2 -> 3 4 1 2

沒錯,迴圈兩次就成功解決問題了,所以最大公約數就是迴圈鏈的數目,也就是執行rotate函數的次數。

我在牛課網上看了,大多數人可能使用沒有改變記憶體的substr,有的人使用三次reverse,沒有見到有人使用GCD。我之前也用reverse,但是現在熟悉了新技能,那就用它吧。

對了,我的思路是以前剖析STL源代碼學習的,如果感興趣可以看STL rotate函數的實現,對不同迭代器重載不同的版本,其中RandomIterator版本使用的就是GCD。



您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前邊以及陸陸續續的介紹了使用Swift3.0開發的服務端應用程式的Perfect框架。本篇博客就做一個階段性的總結,做一個完整的實例,其實這個實例在《Swift3.0服務端開發(一)》這篇博客中已經簡單的介紹過了,本篇博客就來詳細的聊一下這個工程的具體實現細節。當然包括iOS端和服務端的代碼。本篇博 ...
  • Qt使用統一的坐標系統來定位視窗部件的位置和大小。 以屏幕的左上角為原點即(0, 0)點,從左向右為x軸正向,從上向下為y軸正向,這整個屏幕的坐標系統就用來定位頂層視窗; 此外,視窗內部也有自己的坐標系統,它依然以左上角作為原點,從左向右為x軸正向,從上向下為y軸正向,原點、x軸、y軸圍成的區域叫做 ...
  • Flask是一個非常優秀的web框架,到目前為止,我相信關於他的介紹以及非常的多,就算cnblog中,隨便一搜也會有很多內容,但還是拋磚引玉,就當是一個自我的總結 部署環境 安裝python 首先,當然是安裝python環境,去 "官網" 來下載最新的環境(我選擇最新的3.6版本) 然後一路下一步即 ...
  • ECMAScript語言的標準是由Netscape、Sun、微軟、Borland等公司基於JavaScript和JScript錘煉、定義出來的。 ECMAScript可以為不同種類的宿主環境提供核心的腳本編程能力。ECMAScript僅僅是一個描述,定義了腳本語言的所有屬性、方法和對象。 ...
  • Spring_屬性配置細節 1、若字面值包含特殊字元,可以使用<![CDATA[]] 把字面值包裹起來 例 : 2、ref屬性來建立bean之間的引用關係和級聯屬性賦值 2.1 定義User.java(見上一篇文章)和Manager.java Bean 2、2 配置spring xml文件 3、配置 ...
  • 本工作室專註開發南方湛江海南七星彩投註網站系統建設開發,出租,支持帶手機版投註,以及手機APP開發,安裝版本,蘋果版。 QQ私聊:2046 771739 演示圖: ...
  • 操作系統: CentOS 6.5_x64開發語言: Python 適用場景:程式異常退出後需要及時啟動的情況。 源碼地址: https://github.com/mike-zhang/processGuarder 原理 通過ps檢查進程是否存在,如果不存在則啟動 使用 ./processGuarde ...
  • maven-compiler-plugin 編譯Java源碼,一般只需設置編譯的jdk版本 maven-dependency-plugin 用於複製依賴的jar包到指定的文件夾里 maven-jar-plugin 打成jar時,設定manifest的參數,比如指定運行的Main class,還有依賴 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...