我正在尝试使用正则表达式解决codingbat问题,无论它是否在网站上有效。
到目前为止,我有以下代码,它们不会在两个连续的相等字符之间添加*
。相反,它只是推翻它们并用一个字符串替换它们。
public String pairStar(String str) {
Pattern pattern = Pattern.compile("([a-z])\\1", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(str);
if(matcher.find())
matcher.replaceAll(str);//this is where I don't know what to do
return str;
}
我想知道如何继续使用正则表达式并替换整个字符串。如果需要,我认为递归系统可以提供帮助。
答案 0 :(得分:2)
这有效:
while(str.matches(".*(.)\\1.*")) {
str = str.replaceAll("(.)\\1", "$1*$1");
}
return str;
搜索正则表达式(.)\\1
:
(.)
表示“任意字符”(.
),括号创建一个组 - 第1组(第一个左括号)\\1
,正则表达式为\1
(java文字String
必须使用另一个反斜杠转义反斜杠)表示“第一个组” - 这种术语称为“返回参考“所以(.)\1
一起意味着“任何重复的角色”
替换正则表达式$1*$1
:
$1
字词表示“作为第1组捕获的内容”
从技术上讲,该网站上要求的解决方案是一个递归解决方案,所以这里是递归实现:
public String pairStar(String str) {
if (!str.matches(".*(.)\\1.*")) return str;
return pairStar(str.replaceAll("(.)\\1", "$1*$1"));
}
答案 1 :(得分:1)
我不懂java,但我相信在java或者正则表达式中有字符串的替换函数。你的匹配字符串是
([a-z])\\1
替换字符串将是
$1*$1
经过一番搜索,我认为你正在寻找这个,
str.replaceAll("([a-z])\\1", "$1*$1").replaceAll("([a-z])\\1", "$1*$1");
答案 2 :(得分:1)
FWIW,这是一个非递归的解决方案:
public String pairStar(String str) {
int len = str.length();
StringBuilder sb = new StringBuilder(len*2);
char last = '\0';
for (int i=0; i < len; ++i) {
char c = str.charAt(i);
if (c == last) sb.append('*');
sb.append(c);
last = c;
}
return sb.toString();
}
答案 3 :(得分:1)
这是我自己的解决方案。
递归解决方案(可能或多或少是问题所针对的解决方案)
public String pairStar(String str) {
if (str.length() <= 1) return str;
else return str.charAt(0) +
(str.charAt(0) == str.charAt(1) ? "*" : "") +
pairStar(str.substring(1));
}
如果你想抱怨substring
,那么你可以编写一个辅助函数pairStar(String str, int index)
来完成实际的递归工作。
正则表达式单线程单功能呼叫解决方案
public String pairStar(String str) {
return str.replaceAll("(.)(?=\\1)", "$1*");
}
两种解决方案都具有相同的精神。它们都检查当前字符是否与下一个字符相同。如果它们相同,则在两个相同的字符之间插入*
。然后我们继续检查下一个字符。这是为了从输入a*a*a*a
生成预期输出aaaa
。
"(.)\\1"
的正常正则表达式解决方案有一个问题:每个匹配消耗2个字符。结果,我们无法比较第二个字符后面的字符是否是相同的字符。前瞻用于解决此问题 - 它将与下一个字符进行比较而不消耗它。
这类似于递归解决方案,我们比较下一个字符str.charAt(0) == str.charAt(1)
,同时在子字符串上递归调用函数,只删除当前字符pairStar(str.substring(1)
。