字符串循環移位問題是面試中比較容易遇到的,就是輸入一個字符串和一個整數,原地輸出移位后的字符串。
不同的考官可能對程序的具體要求不同,這里要求空間復雜度為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)。