题目一:输入一个英文句子,翻转句子中单词的顺序,但单词内字符串的顺序不变。例如输入字符串:“I am a student”,则输出“student a am I”.
将整个过程分成两步,
第一步:旋转句子中的所有字符,比如翻转I am a student中所有单词得到:“tneduts a ma I”。此时不但翻转了句子中单词的顺序,就连单词内字符顺序也翻转了。
第二步:再次翻转每个单词的顺序,这样就得到了”student a am I“。
该算法的主要关键点是找到每个单词的分界点,即找准每个单词间的空格,找好空格位置后,通过调用旋转函数后,就可实现了单词的重新旋转
题目二:字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串坐旋转操作的功能。比如输入字符串“abcdefg"和数字2,该函数将返回左旋转两位得到的结果:”cdefgab"
要找到字符串旋转时每个字符移动的规律,不是一件容易的事。那么我们是不是可以从解决第一个问题的思路中找到启发呢?在第一个问题中,如果输入的字符串之中只有两个单词,比如”hello World",那么翻转这个句子中的单词顺序就得到了“world hello",比较这两个字符串,我们是不是可以把”world hello"看成是把原始字符串“hello world"的前面若干个字符转移到后面?也就是说这两个问题非常相似,我们同样可以通过反转字符串的办法来解决第二个问题。
以”abcdeftg"为例,我们可以把它分为两个部分,由于想把它的前两个字符一道后面,我们就把前面两个字符分到第一部分,把后面的所有字符都分到第二个部分。我们先反转这两部分,于是就得到了“bagfedc",接下来我们再翻转整个字符串,得到了”cdefgab"刚好就是把原始字符串左旋转2位的结果。
该算法主要是找准需要翻转的两部分。通过3次调用reverse函数就能实现翻转
(1)翻转字符串前面的n个字符
(2)翻转字符串后面部分的字符
(3)翻转整个字符串
代码:
public class Offer42 {
//问题1,翻转单词顺序
//方法1
public void reverse(char [] data, int begin, int end){
if(data == null || end-begin<1|| data.length<2)
return;
while(begin<end){
char temp = data[begin];
data[begin] = data[end];
data[end] = temp;
begin++;
end--;
}
}
public String reverseSentence(String str){
if(str == null || str.length()<2)
return str;
char [] chars = str.toCharArray();
int length = chars.length-1;
reverse(chars, 0, length);// 先把整个字符串反过来
int begin = 0;
int end = 0;
while(end <length){
if(chars[end] == ' '){
reverse(chars, begin, end-1);
begin = end+1;
}
end++;
}
reverse(chars, begin, end);
return String.valueOf(chars);//将字符数组以字符串的形式输出
}
//方法2
public String reverseSentence_2(String str){
if(str == null || str.length()<2)
return str;
char [] chars = str.toCharArray();
int length = chars.length-1;
reverse(chars, 0, length);// 先把整个字符串反过来
int begin = 0;
int end = 0;
while(begin<length){
if(chars[begin] == ' '){//空格
begin++;
end++;
}else if(end == chars.length || chars[end] == ' '){//判断end是否找到了句子的开头或者是否到了句子的结尾
reverse(chars, begin, end-1);
end++;//end继续向后移动
begin = end;//把空格处赋给start,让start重新指向下一个单词的开始
}else
end++;
}
return String.valueOf(chars);
}
//方法3
public String reverseSentence_3(String str){
StringBuilder sb = new StringBuilder("");
if(str==null||str.length()<=0|| str.trim().equals("")){//trim()返回字符串的副本,省略前导和尾随空格。
return str;
}
String [] strSet = str.split(" ");//过滤空格
int length = strSet.length;
for(int i = length-1;i>0;i--){
sb.append(strSet[i]+" ");
}
sb.append(strSet[0]);
return sb.toString();
}
//问题2
public String leftRotateString(String str, int n){
if(str == null || n<=0 || n>str.length()|| str.length()<2)
return str;
char [] chars = str.toCharArray();
int length = chars.length;
reverse(chars, 0, n-1);// 翻转前n个字符
reverse(chars, n, length-1);// 翻转后面的字符
reverse(chars, 0, length-1);// 翻转整个字符串
return String.valueOf(chars);
}
public static void main(String[] args) {
Offer42 of42 = new Offer42();
/*
//功能测试,1,句子中有多个单词
String str1 = "I am a student.";
//System.out.println(of42.reverseSentence(str1));
//System.out.println(of42.reverseSentence_2(str1));
System.out.println(of42.reverseSentence_3(str1));
//功能测试,2,句子中只有一个单词
String str2 = "student";
//System.out.println(of42.reverseSentence(str2));
//System.out.println(of42.reverseSentence_2(str2));
System.out.println(of42.reverseSentence_3(str2));
//特殊输入测试,3,字符串指针为NULL指针
String str3 = null;
//System.out.println(of42.reverseSentence(str3));
//System.out.println(of42.reverseSentence_2(str3));
System.out.println(of42.reverseSentence_3(str3));
//特殊输入测试,4,字符串内容为空
String str4 = "";
//System.out.println(of42.reverseSentence(str4));
//System.out.println(of42.reverseSentence_2(str4));
System.out.println(of42.reverseSentence_3(str4));
//特殊输入测试,5,字符串内容只有空格
String str5 = " ";
//System.out.println(of42.reverseSentence(str5));
//System.out.println(of42.reverseSentence_2(str5));
System.out.println(of42.reverseSentence_3(str5));
*/
//功能测试,1,把长度为n的字符串左旋转0个字符
String str1 = "abcdefg";
int n1 = 0;
System.out.println(of42.leftRotateString(str1, n1));
//功能测试,2,把长度为n的字符串左旋转1个字符
String str2 = "abcdefg";
int n2 = 1;
System.out.println(of42.leftRotateString(str2, n2));
//功能测试,3,把长度为n的字符串左旋转3个字符
String str3 = "abcdefg";
int n3 = 2;
System.out.println(of42.leftRotateString(str3, n3));
//功能测试,4,把长度为n的字符串左旋转n-1个字符
String str4 = "abcdefg";
int n4 = str4.length()-1;
System.out.println(of42.leftRotateString(str4, n4));
//功能测试,5,把长度为n的字符串左旋转n个字符
String str5 = "abcdefg";
int n5 = str4.length();
System.out.println(of42.leftRotateString(str5, n5));
//功能测试,6,把长度为n的字符串左旋转n+1个字符
String str6 = "abcdefg";
int n6 = str4.length()+1;
System.out.println(of42.leftRotateString(str6, n6));
//特殊输入测试,7,字符串的指针为NULL
String str7 = null;
int n7 = str4.length();
System.out.println(of42.leftRotateString(str7, n7));
}
}
运行结果(问题1):
student. a am I
student
null
(这行啥都没有)
(这里前面有三个空格)
运行结果(问题2):
abcdefg
bcdefga
cdefgab
gabcdef
abcdefg
abcdefg
null