zoukankan      html  css  js  c++  java
  • 翻转单词顺序VS左旋转字符串

    已经有很多书籍和博客讲过这两个问题了,也有很多的解法,但是有的解法不够好,或者写的不太清楚,因此我再重新把这两个问题解释下,并用Java代码实现。

    之所以将这两个问题放在一起去讨论,一方面是因为这两个问题都需要去反转字符串,另一方面是在反转完字符串后,各自的处理方法不太一样,是两个比较常见的面试笔试题目。

    翻转单词顺序(曾经的微软面试题目):

    问题描述:给定一个英文句子,将这个句子中每个单词作为整体进行反转,但是单词内字符顺序不变。

    例如:输入字符串“I am a student.”,输出"student. a am I"。

    问题分析:这个题目是一个比较经典的字符串处理题目,很多公司面试时都会考类似的题目。其实这个问题比较简单,编程前需要先分析清楚,再去写程序。两步就可以完成:

                  第一步:可以先反转句子中所有的字符。样例中"I am a student." 经过第一步后变成".tneduts a ma I",可以定义一个方法或函数,专门用来反转字符串。

                  第二步:再反转每个单词中字符的顺序。".tneduts a ma I" 经过第二步变成“student. a am I”,这一步中可以把空格作为单词之间的分隔符,但是要特别注意最后一个单词的处理,

                             因为最后一个单词没有空格结尾,可以将最后一个单词特别处理。

                  下面使用Java代码实现,方法reverse()专门用来反转字符串,方法fanzhuan()实现了第二步的功能。 

    左旋转字符串:

    问题描述:给定一个字符串,要求把字符串前面的若干个字符移动到字符串的尾部。要求时间复杂度为 O(n),空间复杂度为 O(1)。

    例如:输入字符串“abcdef”,把前面的2个字符'a'和'b'移动到字符串的尾部,使得原字符串变成字符串“cdefab”。

    问题分析:使用暴力法可以实现要求的功能,但是暴力法效率比较低,可以满足空间复杂度O(1),但是不满足题目中要求的时间复杂度O(n),因此需要寻找新的解法。

                 这里提供了一种方法,叫做三步反转法。具体解释如下:

                 将一个字符串分成X和Y两个部分,在每部分字符串上定义反转操作,如X^T,即把X的所有字符反转(如,X="abc",那么X^T="cba"),那么可以得到这个结论:(X^T Y^T)^T=YX,这样就解决了字符串的反转问题。

                 例如,字符串 abcdef ,若要让abc反转到def的后面,只要三步即可:

                          第一步:首先将原字符串分为两个部分,即X:abc,Y:def;

                          第二步:将X反转,X->X^T,即得:abc->cba;将Y反转,Y->Y^T,即得:def->fed。

                          第三步:反转上述步骤得到的结果字符串X^TY^T,即反转字符串cbafed的两部分(cba和fed)给予反转,cbafed得到defabc,形式化表示为(X^TY^T)^T=YX,这就实现了整个反转。

    下面的Java代码中,方法zuofanzhuan()实现了这个操作,当然也需要反转每个每个部分的方法reverse()。

    注意:Java语言中字符串包已经提供了很多方法可以直接实现反转操作,程序员直接调用即可,但是本文所讲的是更通用的方法,在任何编程语言中都可以使用的方法,并且讲出了问题的实质,提供了一种处理字符串的思想,

            这也是面试和笔试考官希望看到的答案,因此,这里的方法需要牢牢掌握,方便以后的字符串编程。

    下面是具体的Java代码实现,读者可以很容易的改写成其他语言实现:

     1 import java.util.*;
     2  class Test {
     3     public static String reverse(String str){            //将一个字符串进行反转
     4         StringBuilder strb=new StringBuilder(str);       //将其转换为可变字符串
     5         int low=0,high=strb.length()-1;
     6         while(low<high){                                //将左边位和右边位依次进行交换
     7             char ch=strb.charAt(low);
     8             strb.setCharAt(low,strb.charAt(high));
     9             strb.setCharAt(high,ch);    
    10             low++;  high--;
    11         }
    12             return strb.toString();                    //将可变字符串变成不可变字符串,并返回
    13     }
    14     
    15     public static String fanzhuan(String str){         //翻转每个单词的顺序
    16           str=Test.reverse(str);                       //先整体反转
    17           String strfinal=new String("");
    18           String str1=new String("");
    19           for(int i=0;i<str.length();i++)              //再反转每个单词的顺序
    20               if(str.charAt(i)==' ')
    21                   { 
    22                   strfinal=strfinal+Test.reverse(str1)+str.charAt(i);
    23                   str1="";
    24                   }
    25               else {
    26                    str1+=str.charAt(i);
    27                    if(i==str.length()-1)               //对最后一个单词进行处理,因为最后一个单词没有空格了
    28                        strfinal=strfinal+Test.reverse(str1);
    29                    }
    30           return strfinal;
    31     }
    32     
    33     public static String zuoxuanzhuan(String str,int k){
    34         int n=str.length();
    35         if(n==0 || k<=0|| k>n )                    //如果字符串长度为0,或者k 不在字符串长度的范围内,则返回原来的字符串
    36             return str;         
    37         String str1=new String("");               //存储第一部分,前k个字符
    38         String str2=new String("");               //存储第二部分,后面n-k个字符
    39         for(int i=0;i<k;i++)
    40             str1+=str.charAt(i);
    41         for(int i=k;i<n;i++)
    42             str2+=str.charAt(i);
    43         return reverse(reverse(str1)+reverse(str2));    //采用三步反转法
    44     }
    45     }
    46  
    47 public class Main {
    48     public static void main(String[] args) {
    49       String str=new String("I am a student.");
    50       System.out.println("翻转句子前为:"+str);
    51       System.out.println("翻转句子后为:"+Test.fanzhuan(str));
    52       int k=3;
    53       str="abcdef";
    54       System.out.println("左旋转字符串前为:"+str);
    55       System.out.println("左旋转字符个数为:"+k);
    56       System.out.println("左旋转字符串后为:"+Test.zuoxuanzhuan(str,k));
    57       
    58     }
    59 
    60 }
    View Code

    输出结果为:

    翻转句子前为:I am a student.
    翻转句子后为:student. a am I
    左旋转字符串前为:abcdef
    左旋转字符个数为:3
    左旋转字符串后为:defabc

  • 相关阅读:
    4 Apr 18 软件开发目录 logging模块的使用 序列化(Json, Pickle) os模块
    3 Apr 18 内置函数 列表生成式与生成器表达式 模块的使用之import 模块的使用之from…import…
    2 Apr 18 三元表达式 函数递归 匿名函数 内置函数
    30 Mar 18 迭代器 生成器 面向过程的编程
    29 Mar 18 函数 有参、无参装饰器
    28 Mar 18 函数
    27 Mar 18 函数的参数
    26 Mar 18 函数介绍
    23 Mar 18 文件处理
    22 Mar 18 补充数据类型+字符编码+文件处理
  • 原文地址:https://www.cnblogs.com/guozhenqiang/p/5426787.html
Copyright © 2011-2022 走看看