[算法] 字符串循环左移

问题

  • 给定一个字符串 S [ 0... N 1 ] ,要求把 S 的前 k 个字符串移动到 S 的尾部,如把字符串 a b c d e f ,前面的两个字符 a b 移动到移动到字符串的尾部,得到新字符串 c d e f a b :即字符串循环左移 k 个:

    • 循环左移 n + k 2和 k 2的效果相同;
    • 循环左移 k 位等价于循环右移 n k 位。
  • 算法要求

    • 时间复杂度为 O ( n ) ,空间复杂度为 O ( 1 )

分析

  • 暴力移位法
    • 每次循环左移一位,调用 k 次即可
    • 时间复杂度为 O ( k N ) ,空间复杂度为O(1)
  • 三次拷贝法
    • S [ 0... k ] -> T [ 0... k ]
    • S [ k + 1... N 1 ] -> S [ 0... N k 1 ]
    • T [ 0... k ] -> S [ N k . . . N 1 ]
    • 时间复杂度 O ( N ) ,空间复杂度 O ( k )
  • 转置法
    • (X’Y’)’ = YX
      • a b c d e f
      • X = a b X = b a
      • Y = c d e f Y = f e d c
      • ( X Y ) = ( b a f e d c ) = c d e f a b
    • 时间复杂度为 O ( N ) ,空间复杂度为 O ( 1 )

代码实现

代码实现如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 */

猜你喜欢

转载自blog.csdn.net/zkp_java/article/details/80767475
今日推荐