"Coding Interview Guide" -- 翻转字符串

题目

  给定一个字符类型的数组chas,请在单词间做逆序调整。只要做到单词顺序逆序即可,对空格的位置没有特别要求

  举例,如果把chas看作字符串为"dog loves pig",调整成"pig loves dog";如果把chas看作字符串为"I'm a student.",调整成"student. a I'm"

要求

  如果chas长度为N,要求时间复杂度为O(N),空间复杂度为O(1)

分析

  首先将整个单词序列逆序,逆序后再将每个单词逆序,即可将单词顺序逆序。如"dog loves pig",首先将整个单词序列逆序得到"gip sevol god",然后将每个单词逆序,得到"pig loves dog"。整个过程都实在元字符数组的基础上完成的,所以空间复杂的为O(1),全程总共只遍历了整个字符数组两次,所以时间复杂度为O(N)  

 1 public void rotateWord(char[] chas)
 2 {
 3     if(chas == null || chas.length == 0)
 4     {
 5         return;
 6     }
 7 
 8     reverse(chas, 0, chas.length -1);      // 先将整个单词序列逆序
 9     int left = -1;         // left跟踪单词的左边界
10     int right = -1;        // right跟踪单词的右边界
11     for(int i = 0; i < chas.length; i++)
12     {
13       if(chas[i] != ' ')
14       {
15           left = i == 0 || chas[i-1] == ' ' ? i : left;    
16           right = i == chas.length || chas[i+1] == ' ' ? i : right;
17       }
18       if(left != -1 && right != -1)         
19       {
20           reverse(chas, left, right);        // 然后将单个单词逆序
21           left = -1;
22           right = -1;
23       }
24 
25     }
26 }
27                 
28             
29 public void reverse(char[] chas, int start, int end)
30 {
31     char temp;
32         
33     while(start < end)
34     {
35       temp = chas[start];
36       chas[start] = chas[end];
37       chas[end] = temp;
38       start++;
39         end--;
40     }        
41 }
42 
43     

题目

  给定一个字符类型的数组chas和一个整数size,请把大小为size的左半区整体移到右半区,右半区整体移到左边

  举例,如果把chas看作字符串为"ABCDE",size=3,调整成"DEABC"

要求

  如果chas长度为N,要求时间复杂度为O(N),空间复杂度为O(1)

分析

  可以先将字符数组整体翻转,然后将长度为chas.length-size的左半区和长度为size的右半区分别翻转。或者先将长度为size的左半区逆序,然后将长度为chas.length-size的右半区逆序,最后整体逆序

方法一:

 1 public void rotate(char[] chas, int size)
 2 {
 3     if(chas == null || chas.length == 0)
 4     {
 5       return;
 6     }
 7     reverse(chas, 0, chas.length-1);           // 先整体逆序
 8     reverse(chas, 0, chas.length-size-1);     // 将翻转后得到的数组中长度为chas.length-size的左半区逆序
 9     reverse(chas, chas.length-size, chas.length-1);  // 长度为size的右半区逆序
10 }
11 
12 public void rotate(char[] chas, int size)
13 {
14     if(chas == null || chas.length == 0)
15     {
16       return;
17     }
18 
19     reverse(chas, 0, size-1);             // 将长度为size的左半区逆序
20     reverse(chas, size, arr.length-1);  // 长度为arr.length-size的右半区逆序
21     reverse(chas, 0, arr.length-1);     // 整体逆序
22 }

方法二:

 1 public void rotate(char[] chas, int size)
 2 {
 3    if(chas == null || chas.length < size)
 4     {
 5         return;
 6     }
 7 
 8     int start = 0;
 9     int end = chas.length - 1;
10     int lpart = size;
11     int rpart = chas.length - size;
12     int m = Math.min(lpart, rpart);
13     int d = lpart - rpart;
14     while(true)
15     {
16         exchange(chas, start, end, m);
17         if(d == 0)
18         {
19             break;
20         }
21         else if(d > 0)
22         {
23             start += m;
24             lpart = d;
25         }
26         else
27         {
28             end -= m;
29             rpart = -d;
30         }
31         m = Math.min(lpart, rpart);
32         d = lpart - rpart;
33     }
34 }
35 
36 public void exchange(char[] chas, int start, int end, int size)
37 {
38     end = end - size + 1;
39     char temp = 0;
40     while(size-- != 0)
41     {
42         temp = chas[start];
43         chas[start] = chas[end];
44         chas[end] = temp;
45         start++;
46         end++;
47     }
48 }

来源:左程云老师《程序员代码面试指南》

原文地址:https://www.cnblogs.com/OoycyoO/p/10886242.html