题目一:输入一个英文句子,翻转句子中单词的顺序,但单词内字符串的顺序不变。例如输入字符串:“I am a student”,则输出“student a am I”.
程序运行结果:
![](https://img-blog.csdn.net/20160925201922338)
![](https://img-blog.csdn.net/20160925201926260)
算法分析:
算法1:
将整个过程分成两步,
第一步:旋转句子中的所有字符,比如翻转I am a student中所有单词得到:“tneduts a ma I”。此时不但翻转了句子中单词的顺序,就连单词内字符顺序也翻转了。
第二步:再次翻转每个单词的顺序,这样就得到了”student a am I“。
该算法的主要关键点是找到每个单词的分界点,即找准每个单词间的空格,找好空格位置后,通过调用旋转函数后,就可实现了单词的重新旋转。
public char[] reverseSentence(char[] data){
if(data == null || data.length < 1)
return data;
reverse(data,0,data.length - 1);
System.out.println("reverse后的顺序为:");
for(int j = 0;j <data.length;j++)
System.out.print(data[j]);
System.out.println();
int start = 0; //start用于寻找每个单词的开头
int end = 0; //end用于寻找每个单词后面的空格
while(start < data.length){
if(data[start] == ' '){
start++;
end++;
}
else if(end == data.length || data[end] == ' '){ //判断end是否找到了句子的开头或者是否到了句子的结尾
reverse(data,start,end - 1); //找到空格后,将空格前面的单词翻转,这样单词的顺序就对了
end++; //end继续向后移动
start = end; //把空格处赋给start,让start重新指向下一个单词的开始
}
else{
end++;
}
}
return data; //返回的data即为最后旋转后的结果
}
算法2.
使用split函数,通过该函数判断字符串的空格
public String ReverseMethod2Fun(String str){StringBuffer stringbuffer = new StringBuffer("");if(str.length() <= 0 || str.trim().equals("")){return str;}String[] strSet = str.split(" ");int length = strSet.length;for(int i = length - 1; i > 0;i--){stringbuffer.append(strSet[i] + " ");}stringbuffer.append(strSet[0]);return stringbuffer.toString();}
算法3.
调用递归函数,一个句子实现翻转
public String ReverSentence(String str) {
return (str.lastIndexOf(" ")==-1)?str:str.substring(str.lastIndexOf(" ")+1) +" "+ReverSentence(str.substring(0,str.lastIndexOf(" ")));
}
题目二:字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串坐旋转操作的功能。比如输入字符串“abcdefg"和数字2,该函数将返回左旋转两位得到的结果:”cdefgab"
算法分析:
要找到字符串旋转时每个字符移动的规律,不是一件容易的事。那么我们是不是可以从解决第一个问题的思路中找到启发呢?在第一个问题中,如果输入的字符串之中只有两个单词,比如”hello World",那么翻转这个句子中的单词顺序就得到了“world hello",比较这两个字符串,我们是不是可以把”world hello"看成是把原始字符串“hello world"的前面若干个字符转移到后面?也就是说这两个问题非常相似,我们同样可以通过反转字符串的办法来解决第二个问题。
以”abcdeftg"为例,我们可以把它分为两个部分,由于想把它的前两个字符一道后面,我们就把前面两个字符分到第一部分,把后面的所有字符都分到第二个部分。我们先反转这两部分,于是就得到了“bagfedc",接下来我们再翻转整个字符串,得到了”cdefgab"刚好就是把原始字符串左旋转2位的结果。
该算法主要是找准需要翻转的两部分。通过3次调用reverse函数就能实现翻转
(1)翻转字符串前面的n个字符
(2)翻转字符串后面部分的字符
(3)翻转整个字符串
题目一源程序:
/**************************************************************
* Copyright (c) 2016,
* All rights reserved.
* 版 本 号:v1.0
* 题目描述:翻转单词顺序
* 输入一个英文句子,翻转句子中单词的顺序,但单词内字符串的顺序不变。例如输入字符串:“I am a student”,则输出“student a am I”
* 输入描述:请输入一个英语字符串:
* I am a good student .
* 程序输出:算法1翻转后的输出是:
* reverse后的顺序为:
* . tneduts doog a ma I
* . student good a am I
* 一行代码翻转后的输出是:
* . student good a am I
* 算法2翻转后的输出是:
* . student good a am I
* 问题分析: 无
* 算法描述: 第一步:旋转句子中的所有字符,比如翻转I am a student中所有单词得到:“tneduts a ma I”。
* 此时不但翻转了句子中单词的顺序,就连单词内字符顺序也翻转了。
* 第二步:再次翻转每个单词的顺序,这样就得到了”student a am I“
* 完成日期:2016-09-25
***************************************************************/
package org.marsguo.offerproject42;
import java.util.Scanner;
class SolutionMethod1{
public void reverse(char[] data,int start,int end){
if(data == null || data.length < 1 || start < 0 ||
end > data.length || start > end)
return;
/*
while循环直接将整个句子的所有单词顺序翻转
*/
while (start < end){
char temp = data[start];
data[start] = data[end];
data[end] = temp;
start++;
end--;
}
}
public char[] reverseSentence(char[] data){
if(data == null || data.length < 1)
return data;
reverse(data,0,data.length - 1);
System.out.println("reverse后的顺序为:");
for(int j = 0;j <data.length;j++)
System.out.print(data[j]);
System.out.println();
int start = 0; //start用于寻找每个单词的开头
int end = 0; //end用于寻找每个单词后面的空格
while(start < data.length){
if(data[start] == ' '){
start++;
end++;
}
else if(end == data.length || data[end] == ' '){ //判断end是否找到了句子的开头或者是否到了句子的结尾
reverse(data,start,end - 1); //找到空格后,将空格前面的单词翻转,这样单词的顺序就对了
end++; //end继续向后移动
start = end; //把空格处赋给start,让start重新指向下一个单词的开始
}
else{
end++;
}
}
return data; //返回的data即为最后旋转后的结果
}
/*
使用递归,直接将传入的字符串翻转
*/
public String ReverSentence(String str) {
return (str.lastIndexOf(" ")==-1)?str:str.substring(str.lastIndexOf(" ")+1) +" "+ReverSentence(str.substring(0,str.lastIndexOf(" ")));
}
}
class SolutionMethod2{
public String ReverseMethod2Fun(String str){
StringBuffer stringbuffer = new StringBuffer("");
if(str.length() <= 0 || str.trim().equals("")){
return str;
}
String[] strSet = str.split(" ");
int length = strSet.length;
for(int i = length - 1; i > 0;i--){
stringbuffer.append(strSet[i] + " ");
}
stringbuffer.append(strSet[0]);
return stringbuffer.toString();
}
}
public class ReverseString {
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个英语字符串:");
String str = scanner.nextLine();
scanner.close();
char[] data = new char[str.length()];
data = str.toCharArray();
SolutionMethod1 solution1 = new SolutionMethod1();
System.out.println("算法1翻转后的输出是:");
System.out.println(solution1.reverseSentence(data));
System.out.println("一行代码翻转后的输出是:");
System.out.println(solution1.ReverSentence(str));
SolutionMethod2 solution2 = new SolutionMethod2();
System.out.println("算法2翻转后的输出是:");
System.out.println(solution2.ReverseMethod2Fun(str));
}
}
题目二源程序:
/**************************************************************
* Copyright (c) 2016,
* All rights reserved.
* 版 本 号:v1.0
* 题目描述:左旋转字符串
* 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串坐旋转操作的功能。
* 比如输入字符串“abcdefg"和数字2,该函数将返回左旋转两位得到的结果:”cdefgab"
* 输入描述:请输入一个英语字符串:abcdefg
* 请输入要翻转字符串的前几位:2
* 程序输出:旋转后的字符串为:
* cdefgab
* 问题分析: 无
* 算法描述: 该算法主要是找准需要翻转的两部分。通过3次调用reverse函数就能实现翻转
* (1)翻转字符串前面的n个字符
* (2)翻转字符串后面部分的字符
* (3)翻转整个字符串
* 完成日期:2016-09-25
***************************************************************/
package org.marsguo.offerproject42;
import java.util.Scanner;
class LeftSolutionMethod1{
public void reverse(char[] data,int start,int end){
if(data == null || data.length < 1 || start < 0 ||
end > data.length || start > end)
return;
/*
while循环直接将整个句子的所有单词顺序翻转
*/
while (start < end){
char temp = data[start];
data[start] = data[end];
data[end] = temp;
start++;
end--;
}
}
public char[] leftRotateFunction(char[] data,int n){
if(data == null || n <= 0 )
return null;
int beforestart = 0; //前半段起始位
int beforeend = n-1; //前半段终止位
int afterstart = n; //后半段的起始位
int afterend = data.length-1; //后半段的终止位
reverse(data,beforestart,beforeend); //翻转字符串的前面n个字符
reverse(data,afterstart,afterend); //翻转字符串的后面部分字符
reverse(data,0,data.length-1); //翻转整个字符串
return data; //返回最终翻转后的结果,是一个字符型数组
}
}
public class LeftRotateString {
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个英语字符串:");
String str = scanner.nextLine();
System.out.println("请输入要翻转字符串的前几位:");
int n = scanner.nextInt();
scanner.close();
char[] data = new char[str.length()];
data = str.toCharArray();
LeftSolutionMethod1 leftsolution1 = new LeftSolutionMethod1();
System.out.println("旋转后的字符串为:");
System.out.println(leftsolution1.leftRotateFunction(data, n));
}
}
程序运行结果: