旋转字符串问题
题目描述
给定一个字符串,要求把字符串前面的若干个字符移动到字符串的尾部,如把字符串“abcdef”前面的2个字符'a'和'b'移动到字符串的尾部,使得原字符串变成字符串“cdefab”。请写一个函数完成此功能,要求对长度为n的字符串操作的时间复杂度为 O(n),空间复杂度为 O(1)。
思路
对于这个问题,换一个角度思考一下。
将一个字符串分成X和Y两个部分,在每部分字符串上定义反转操作,如X^T,即把X的所有字符反转(如,X="abc",那么X^T="cba"),那么就得到下面的结论:(X^TY^T)^T=YX,显然就解决了字符串的反转问题。
例如,字符串 abcdef ,若要让def翻转到abc的前头,只要按照下述3个步骤操作即可:
- 首先将原字符串分为两个部分,即X:abc,Y:def;
- 将X反转,X->X^T,即得:abc->cba;将Y反转,Y->Y^T,即得:def->fed。
- 反转上述步骤得到的结果字符串X^TY^T,即反转字符串cbafed的两部分(cba和fed)给予反转,cbafed得到defabc,形式化表示为(X^TY^T)^T=YX,这就实现了整个反转。
代码:
1 import java.util.Scanner; 2 3 public class Test1 { 4 5 static String str1 = "abcdef"; 6 static String str2 = "123456"; 7 static char[] s = {'a','b','c','d','e','f'}; 8 9 public static void main(String[] args) { 10 int n=str1.length(); 11 reverse(str1.toCharArray(), n, 3); 12 // reverse(s, n, 2); 13 } 14 15 /** 16 * 交换两个字符的位置 17 * @param s 18 * @param from 19 * @param to 20 */ 21 static void ReverseString(char[] s,int from,int to){ 22 while (from < to){ 23 s[from] = (char) (s[from] ^ s[to]); 24 s[to] = (char) (s[from] ^ s[to]); 25 s[from] = (char) (s[from] ^ s[to]); 26 from ++; 27 to --; 28 } 29 } 30 31 /** 32 * 分成三部分 分别进行翻转 33 * @param s 34 * @param strLength 35 * @param len 36 */ 37 static void reverse(char[] s,int strLength,int len) { 38 len %= strLength; //若要左移动大于n位,那么和%n 是等价的 39 ReverseString(s, 0, len - 1); //反转[0->m - 1],X->X^T,即 abc->cba 40 System.out.println(s); 41 ReverseString(s, len, strLength - 1); //反转[m->n - 1],Y->Y^T,即 def->fed 42 System.out.println(s); 43 ReverseString(s, 0, strLength - 1); //反转[0->n - 1]整个反转,(X^T Y^T)^T=YX,即 cbafed->defabc。 44 System.out.println(s); 45 } 46 }
结果:我们将三步的每一个结果打印