"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 }
来源:左程云老师《程序员代码面试指南》