【面试算法】——字符串问题(一)

字符串面试题的特点

一.广泛性

  • 字符串可以看做字符串类型的数组,与数组的排序、查找和调整有关

  • 很多其他类型的面试题可以看做字符串类型的面试题。

注意:使用Java实现字符串类型的题目时需要掌握StringBuffer,StringBuilder和toCharArray方法

二、字符串相关概念

1.回文

回文的定义:“回文数”就是正读倒读都一样的整数。如奇数个数字:98789,这个数字正读是98789 倒读也是98789。偶数个数字3223也是回文数。字母 abcba 也是回文。

判断一个字符串是否是回文字符串(Java实现)

public class Test4 {
 2     public static boolean isHuiWen(String text) {
 3         int length = text.length();
 4         for (int i = 0; i < length / 2; i++) {
 5             if (text.toCharArray()[i] != text.toCharArray()[length - i - 1]) {
 6                 return false;
 7             }
 8         }
 9         return true;
10     }
11     
12     public static void main(String[] args) {
13 
14         String text = "abccba";
15         System.out.println(isHuiWen(text));
16     }
17 }

2.子串(连续)

串中任意个连续的字符组成的子序列称为该串的子串

3.子序列(不连续)

最长公共子串(Longest Common Substirng)和最长公共子序列(Longest Common Subsequence,LCS)的区别为:子串是串的一个连续的部分,子序列则是从不改变序列的顺序,而从序列中去掉任意的元素而获得新的序列;也就是说,子串中字符的位置必须是连续的,子序列则可以不必连续。

寻找最大公共子序列:具体方法参照博客(https://blog.csdn.net/amazingcode/article/details/51694332

<1> 枚举法

       这种方法是最简单,也是最容易想到的,当然时间复杂度也是龟速的,我们可以分析一下,刚才也说过了cnblogs的子序列

个数有27个 ,延伸一下:一个长度为N的字符串,其子序列有2N个,每个子序列要在第二个长度为N的字符串中去匹配,匹配一次

需要O(N)的时间,总共也就是O(N*2N),可以看出,时间复杂度为指数级,恐怖的令人窒息。

<2> 动态规划

      既然是经典的题目肯定是有优化空间的,并且解题方式是有固定流程的,这里我们采用的是矩阵实现,也就是二维数组。

第一步:先计算最长公共子序列的长度。

第二步:根据长度,然后通过回溯求出最长公共子序列。

现有两个序列X={x1,x2,x3,...xi},Y={y1,y2,y3,....,yi},

设一个C[i,j]: 保存Xi与Yj的LCS的长度。

using System;
 2 namespace ConsoleApplication2
 3 {
 4     public class Program
 5     {
 6         static int[,] martix;
 7 
 8         static string str1 = "cnblogs";
 9         static string str2 = "belong";
10 
11         static void Main(string[] args)
12         {
13             martix = new int[str1.Length + 1, str2.Length + 1];
14 
15             LCS(str1, str2);
16 
17             //只要拿出矩阵最后一个位置的数字即可
18             Console.WriteLine("当前最大公共子序列的长度为:{0}", martix[str1.Length, str2.Length]);
19 
20             Console.Read();
21         }
22 
23         static void LCS(string str1, string str2)
24         {
25             //初始化边界,过滤掉0的情况
26             for (int i = 0; i <= str1.Length; i++)
27                 martix[i, 0] = 0;
28 
29             for (int j = 0; j <= str2.Length; j++)
30                 martix[0, j] = 0;
31 
32             //填充矩阵
33             for (int i = 1; i <= str1.Length; i++)
34             {
35                 for (int j = 1; j <= str2.Length; j++)
36                 {
37                     //相等的情况
38                     if (str1[i - 1] == str2[j - 1])
39                     {
40                         martix[i, j] = martix[i - 1, j - 1] + 1;
41                     }
42                     else
43                     {
44                         //比较“左边”和“上边“,根据其max来填充
45                         if (martix[i - 1, j] >= martix[i, j - 1])
46                             martix[i, j] = martix[i - 1, j];
47                         else
48                             martix[i, j] = martix[i, j - 1];
49                     }
50                 }
51             }
52         }
53     }
54 }

三、基本操作

(转载博客:https://blog.csdn.net/dc2222333/article/details/70979606

                      https://blog.csdn.net/coldzerace/article/details/79534670

1.字符串的增删改查

首先是String类

(1)使用length()获取字符串的长度:

例:char chars[]={'a','b'.'c'};
    String s=new String(chars);
    int len=s.length();

(2)charAt() 截取一个字符

例:char ch;
    ch="abc".charAt(1); 返回'b'

(3)getChars() 截取多个字符

void getChars(int sourceStart,int sourceEnd,char target[],inttargetStart)
  sourceStart指定了子串开始字符的下标,sourceEnd指定了子串结束后的下一个字符的下标。因此,子串包含从sourceStart到sourceEnd-1的字符。接收字符的数组由target指定,target中开始复制子串的下标值是targetStart。

例:String s="this is a demo of thegetChars method.";
    char buf[]=new char[20];
    s.getChars(10,14,buf,0);

然后是StringBuffer类

(1)length()和capacity()

一个StringBuffer当前长度可通过length()方法得到,而整个可分配空间通过capacity()方法得到。

(2)charAt()和setCharAt()

一个是获取指定位置的字符,一个是设置指定位置的字符

char charAt(int where)
void setCharAt(int where,char ch)

(3)复制数组getChars()

void getChars(int sourceStart,int sourceEnd,char target[],inttargetStart)

(4)append()可把任何类型数据的字符串表示连接到调用的StringBuffer对象的末尾。

例:int a=42;
      StringBuffer sb=new StringBuffer(40);
      Strings=sb.append("a=").append(a).append("!").toString();

(5)insert() 插入字符串

StringBuffer insert(int index,String str)
StringBuffer insert(int index,char ch)
StringBuffer insert(int index,Object obj)
index指定将字符串插入到StringBuffer对象中的位置的下标。

(6)reverse() 颠倒StringBuffer对象中的字符
    StringBuffer reverse()

(7)delete()和deleteCharAt() 删除字符

StringBuffer delete(int startIndex,int endIndex)
StringBuffer deleteCharAt(int loc)

(8)replace() 替换

StringBuffer replace(int startIndex,int endIndex,Stringstr)

(9)substring() 截取子串

String substring(int startIndex)
String substring(int startIndex,int endIndex)

2.字符串的替换


public class StringReplaceEmp{
   public static void main(String args[]){
      String str="Hello World";
      System.out.println( str.replace( 'H','W' ) );
      System.out.println( str.replaceFirst("He", "Wa") );
      System.out.println( str.replaceAll("He", "Ha") );
   }
}

replaceFirst只替换第一个匹配的字符串,而replaceAll替换所有匹配的字符串。

以上代码实例输出结果为: 
Wello World 
Wallo World 
Hallo World

3.字符串的旋转及转换

(1)字符串反转

public class StringReverseExample{ 
public static void main(String[] args){ 
String string=”runoob”; 
String reverse = new StringBuffer(string).reverse().toString(); 
System.out.println(“字符串反转前:”+string); 
System.out.println(“字符串反转后:”+reverse); 
} 
}

(2)字符串小写转大写

public class StringToUpperCaseEmp {
    public static void main(String[] args) {
        String str = "string runoob";
        String strUpper = str.toUpperCase();
        System.out.println("原始字符串: " + str);
        System.out.println("转换为大写: " + strUpper);
    }
}
以上代码实例输出结果为:
原始字符串: string runoob
转换为大写: STRING RUNOOB

(3)字符串大写转小写

toLowerCase()

public class StringToUpperCaseEmp {
    public static void main(String[] args) {
        String str = "STRING RUNOOB";
        String strLower = str.toLowerCase();
        System.out.println("原始字符串: " + str);
        System.out.println("转换为小写: " + strLower);
    }
}
以上代码实例输出结果为:
原始字符串: STRING RUNOOB
转换为大写: string runoob

猜你喜欢

转载自blog.csdn.net/qq_36125072/article/details/81623958