编程题:
给定一串字符串,要求对该字符串处理为:
连续三个相同的,比如AAA变成AA
连续两对相同的,比如AABB变成AAB
(为防止我表达不当,或者您审题失误,这里做一下解释:AAA代表的三个一样的样式,不是说从一堆字符串中找到“AAA”然后转变为“AA”,那太简单了。这里的AAA可以是“aaa”,也可以是“bbb”,更可以是“zzz”等等。同理,AABB也不是代表“AABB”)
常规思路:
对字符串挨个判断,然后符合AAA和AABB样式的,进行相应的处理:
大致这样:
下面这个解法,大致的思路是:
将字符串遍历,然后每个字符和后面的两个字符比较,如果一样,代表是AAA样式;
然后再和后面三个字符比较,如果和第二个一样,和第三个不一样,并且第三个和第四个一样,那么就是符合AABB样式,然后最后再对这些符合条件的字符串处理成AA样式和AAB样式。
中间因为穿插一些分支结构以及判断flag,让代码阅读比较费劲,这里不推荐阅读,只是了解这个思路,知道这个解法比较麻烦即可。
然后才能更能体会到文末那个“一行”代码的解法的“别出心裁”。
public class ScanString {
public String scan(String word){
boolean flag = true;
while(flag){
if(word.length()>2){
StringBuilder stringBuilder = new StringBuilder(word);
int n = 0;
int m = 0;
boolean flag1 = false;
for(int i =0;i<word.length() - 2;i++){
//取AAA
if(String.valueOf(word.charAt(i)).equals(String.valuesOf(word.charAt(i+1))) && String.valueOf(word.charAt(i)).equals(String.valueOf(word.charAt(i+2)))){
n = i;
flag1 = true;
}
}
boolean flag2 = false;
for(int i =0;i<word.length() - 3;i++){
//取AABB
if(String.valueOf(word.charAt(i)).equals(String.valueOf(word.charAt(i +1))) && !String.valueOf(word.charAt(i+1)).equals(String.valueOf(word.charAt(i+2))) && String.valueOf(word.charAt(i+2)).equals(String.valueOf(word.charAt(i+3)))){
m = i+2;
flag2 = true;
}
}
if(n!=0){
stringBuilder.deleteCharAt(n);
}
if(m!=0){
stringBuilder.deleteCharAt(m);
}
word = stringBuilder.toString();
if(!flag1 && !flag2){
flag = false;
}
}else{
flag = false;
}
}
return word;
}
}
上面就是比较简单的思路,就是利用循环,不断的判断,判断出AAA以及AABB的,然后修改成AA以及AAB。
但是可以看出,上面的代码很长一段,并且阅读起来很费劲。
当然你可能有更多好的方法,可以让上面的代码,变成更少的行数,并且更容易阅读,但是如果用正则表达式呢?
用正则表达式,只需要一行:
public class ScanString{
public void scan(String word){
//只需下面一行
word.replaceAll("(.)\\1\\1","$1$1").replaceAll("(.)\\1(.)\\2","$1$1$2");
}
}
这种解决方式,确实很别出心裁,一般遇到字符串处理的时候,大部分都是各种逻辑判断加分支等,很难想到用正则表达式来做这个。
毕竟正则表达式在大多数时候,都是用来限制用户输入了。
下面解释一下上面的正则表达式:
首先是(.)
这个东西是干嘛的呢?
我们知道.
在正则表达式中,就是匹配任意字符
的意思。
至于外面的括号,就是把这个看成一个“组”
后面的\\1
又代表什么呢?
我们前面用括号分了一个组,这个\\1
就是为了获得这个组匹配出的字符,换个词就是,捕获
第一个组匹配出的字符。
那么$1
又代表什么呢?
这个代表将你前面捕获
的字符,拿过来。
所以我们因为(.)
任意匹配到一个字符“c“,然后我们后面跟着连续两个\\1
将这个正则表达式,动态的变成了”ccc“,自然就会去匹配到”ccc“的字符串。
然后我们通过$1$1
,将我们要替换的字符串,动态的变成了”cc“,自然就实现了从”ccc“到”cc“的转变。
第二个同理,只不过\\2
就是第二个组的意思,也就是第二个(.)
,如果将第二个正则表达式的\\2
变成\\1
就相当于匹配AABA的样式了。
至于$2
自然也是同理。