c++反轉字元
這是我在leetcode上看見的題目
嘗試了幾種寫法,耗時均不同,這裡先說一下第一種演算法「交換法」
交換法反轉字元就是從尾部一直向前挪移:
如:abcd = dbca
這是第一次交換,第二次交換就是:
dcba
可以看到每次交換都是首位交換,以此向中心擴充套件,通俗易懂的說就是兩者之間向中心點靠攏,每次交換會交換兩個字元,所以交換時間是:o(s\2)
四個字元兩次就可以完成反轉
實現:宣告乙個函式,這裡leetcode使用的是vector容器,我們也一樣.
void reversestring(std::vector& s)
第二步編寫乙個迴圈:
注意迴圈條件是字元大小/2,因為上面說過每次交換是兩個字元
for(int i = 0;i
這裡我的寫法為了省掉記憶體開闢空間以及記憶體互動的方式,使用加減法來儲存要交換的字元,防止被覆蓋,因為字元也是ascii碼
s[i] += s[(s.size()-i)-1];
這裡說一下這段**
s[i]是指向從0開始的字元下標,比如abcd那麼現在下標就是a
s[(s.size()-i)-1]
這段**是算出字元尾部的座標,每次-i是為了下一次的移動,比如現在是d,那麼下次迴圈i是1,就是b與c的交換了.
最後的-1是為了跳過\0,c/c++裡對字元結尾的定義是\0,不能把\0放到首位,如果\0在首位c/c++會認為這就是這段字元的結束.
這裡+=是為了儲存第一位的值,比如a的ascii是97,d的ascii碼是100,那麼相加就是197
此時s[i]=197相當於儲存了兩個字元
s[(s.size()-i)-1] = s[i] - s[(s.size()-i)-1];
這段**就是把末尾的值減去s[i],也就是197-d的ascii碼就等於了a的ascii碼,這樣尾部就有了a
同時還需要把首部的值在減去末尾的值,因為末尾的值剛好是a,那麼197-a的ascii碼就等於了d
s[i] -= s[(s.size()-i)-1];
完整**:
可惜力扣那邊測試,我們的演算法還是比較慢的,這裡就要想想別的辦法,因為我們上面的演算法造成了一部分的計算,還有記憶體資料交換,還是比較耗時的
c++內建了一種函式move,這個函式的用法是直接將乙個值變成左值,也就是立即數的方式,直接跟著指令集去運算,那麼就可以直接不用記憶體的方式去做這些工作了
比如:int a = 10;
int b = 0;
b = a;
如果想要讓b=a,cpu需要到a的記憶體裡取資料,複製乙份資料然後再到b的記憶體位址裡,把資料寫入
這個過程比較繁瑣,但是move不一樣,這個函式可以把a裡的值直接變成左值返回
b = std::move(a)
則變成了:b = 10;
如果不實用move則會翻譯成:b = &a;
這裡不用指令集的方式表示,這樣表示更加的直觀,
彙編的方式就是:
move方式:
mov byte ptr ds:[b],10
非move方式:
mov ax, byte ptr ds:[a] //取出a的值
mov byte ptr ds:[b],ax //放入b中
這裡彙編是大致寫了一下,詳細可以去返彙編看一下
我們修改一下**加上move試試:
for(int i = 0;i
看下力扣測試:
速度一下快了很多,也證實了我們上面說的.有時候演算法固然重要,但是編譯優化也很重要,很多硬體加速就是這樣的方法,使用一些特定的指令集.
上面這套演算法因為有了move的方式,可以省略記憶體訪問,這裡我們就完全沒必要在進行運算了,直接用乙個記憶體變數來儲存臨時的值:
char _c = s[i];
s[i] = std::move(s[(s.size()-i)-1]);
s[(s.size()-i)-1] = std::move(_c);
因為不用計算,也不用去取位址,看一下力扣的測試:
如果你想更懶一點,你可以使用swap函式直接實現,不過這樣就丟失了這道題的意義了.
for(int i = 0;i
move的方式就是我在查閱c++的**時找到的加速方法,因為我發現c++提供的一些函式,或是c,提供的一些基礎函式總是比我們自己寫的要快,我一開始以為是他們的演算法比較好,後來我去查閱了一些glibc的**和c++的一些實現,發現內部內嵌彙編極多,都是使用彙編優化,還有一些編譯器指令優化比如move,雖然說可以調整優化編譯器等級,但是這些細節往往是最重要的.
swap函式的實現:
template inline
void _swap(_ty& _left, _ty& _right)
注意c++的實現裡有乙個inline宣告,這是乙個類似c語言的巨集展開的宣告
比如你的函式add
前面加上inline宣告以後,你在別處呼叫的時候,會直接變成實現**,省去了函式呼叫的棧儲存位址跳轉等等開銷. 這是c++特有的關鍵字
演算法 反轉字串與反轉單詞
題目 將字串內容進行倒置,比如 i like beijing.經過函式後變為 gnijied ekil i。解題思路 首先題目說的很明確,就是反轉字串,不是列印,也不是建立乙個新的字串,而是改變原資料,最簡單的思路就是將第乙個字元和最後乙個交換,第二個和倒數第二個交換,依次迴圈,函式可以返回乙個標誌...
Kmp字元匹配演算法優化C 實現
c 實現kmp字元匹配演算法的優化版 標頭檔案 kmpalgorithm.h ifndef kmpalgorithm h define kmpalgorithm h include include class kmpalgorithm int index kmp int pos 字元匹配函式 end...
python演算法 字串反轉與單鏈表的反轉
1.字串反轉 字串反轉有很多種方式,舉例其中常見的3種 a hello a reverse a 1 print a reverse b yangyangchi b list list b b list.reverse b reverse join b list print b reverse def...