旋转字符串问题

题目描述

给定一个字符串,要求把字符串前面的若干个字符移动到字符串的尾部,如把字符串“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个步骤操作即可:

  1. 首先将原字符串分为两个部分,即X:abc,Y:def;
  2. 将X反转,X->X^T,即得:abc->cba;将Y反转,Y->Y^T,即得:def->fed。
  3. 反转上述步骤得到的结果字符串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 }

结果:我们将三步的每一个结果打印

 

posted @ 2018-12-03 22:24  夏末秋涼  阅读(601)  评论(0编辑  收藏  举报