算法题-字符串循环移位问题

字符串循环移位问题是面试中比较容易遇到的,就是输入一个字符串和一个整数,原地输出移位后的字符串。

不同的考官可能对程序的具体要求不同,这里要求空间复杂度为O(1)。

这里给出两种解答方法。

(1)将移动n位看做“每次移动一位,共操作n次”,这是一种化整为零的思维方法。只要能想到这一步,相信下面的代码就不难写出了:

 1 void shift_1(char* str)
 2 {
 3     int len = strlen(str);
 4     if(len <= 1)
 5         return;
 6     char temp = str[len-1];
 7     for(int i=len-1; i>= 1; i--)
 8         str[i] = str[i-1];
 9     str[0] = temp;
10 }
11 void shift_n(char* str, int n)
12 {
13     if(! str)
14         return;
15     for(int i=1; i<= n; i++)
16         shift_1(str);
17 }

很显然这个算法的时间复杂度为O(nl), 空间复杂度为O(1)。其中l为字符串长度。

(2)观察移位后的字符串和原串的差别,字符串移n位相当于把前n位挪到了后面,而把后n位移到前面。

设字符串长为L,把字符串分成2个部分,前(L-n)个字符看做子串A,后n个字符看做子串B,则字符串可用AB表示。完成移位操作后新串为BA。

那么移位的过程就可以看做AB到BA的过程。

用A’表示A的反序串,B’表示B的反序串,那么 BA = B”A” =(A’B’)’。 代码如下:

 1 // 将一个字符串中某个子串反序
 2 void reverseOrder(char* str, int p, int q)
 3 {
 4     char temp;
 5     while(p < q)
 6     {
 7         temp = str[p];
 8         str[p] = str[q];
 9         str[q] = temp;
10         p ++;
11         q --;
12     }
13 }
14 void shift_n(char* str, int n)
15 {
16     if( !str)
17         return;
18     int len = strlen(str);
19     int t = n % len;
20     reverseOrder(str, 0, len - t -1);
21     reverseOrder(str, len - t, len -1);
22     reverseOrder(str, 0, len -1);
23 }

算法的空间复杂度为O(1)。把赋值操作作为考量时间复杂度的基本单位,3次调用reverseOrder函数总共执行赋值操作3l,则算法的时间复杂度为O(l)。

点赞