问题
给定一个字符串 S[0...N−1] S [ 0... N − 1 ] ,要求把 S S 的前个字符串移动到 S S 的尾部,如把字符串,前面的两个字符 a a 、移动到移动到字符串的尾部,得到新字符串 cdefab c d e f a b :即字符串循环左移 k k 个:
- 循环左移2和 k k 2的效果相同;
- 循环左移位等价于循环右移 n−k n − k 位。
算法要求
- 时间复杂度为 O(n) O ( n ) ,空间复杂度为 O(1) O ( 1 )
分析
- 暴力移位法
- 每次循环左移一位,调用 k k 次即可
- 时间复杂度为,空间复杂度为O(1)
- 三次拷贝法
- S[0...k] S [ 0... k ] -> T[0...k] T [ 0... k ]
- S[k+1...N−1] S [ k + 1... N − 1 ] -> S[0...N−k−1] S [ 0... N − k − 1 ]
- T[0...k] T [ 0... k ] -> S[N−k...N−1] S [ N − k . . . N − 1 ]
- 时间复杂度 O(N) O ( N ) ,空间复杂度 O(k) O ( k )
- 转置法
- (X’Y’)’ = YX
- 如 abcdef a b c d e f
- X=ab X = a b , X′=ba X ′ = b a
- Y=cdef Y = c d e f , Y′=fedc Y ′ = f e d c
- (X′Y′)′=(bafedc)′=cdefab ( X ′ Y ′ ) ′ = ( b a f e d c ) ′ = c d e f a b
- 时间复杂度为 O(N) O ( N ) ,空间复杂度为 O(1) O ( 1 )
- (X’Y’)’ = YX
代码实现
代码实现如CirculRotateString.hpp所示:
#ifndef CirculRotateString_hpp #define CirculRotateString_hpp #include <stdio.h> // 翻转字符串s的from到to1的字符 void reverseString(cahr* s, int from, int to) { while (from < to) { char t = s[from]; s[from++] = s[to]; s[to--] = t; } } // 长度为n的字符串循环左移m位 void leftRotateString(char* s, int n, int m) { m %= n; // 循环左移m位和循环左移(m%=n)位等价 reverseString(s, 0, m-1); // 翻转0~(m-1)区间的字符串 reverseString(s, m, n-1); // 翻转m~(n-1)之间的字符串 reverseString(s, 0, n-1); // 翻转0~(n-1)之间的字符串 } #endif /* CirculRotateString_hpp */
- 暴力移位法