我编写了以下解决方案,除了有标点符号外,它有效。我想知道是否有O(1)空间复杂度和O(字符串长度)时间复杂度解决方案,不使用reverse()方法,或类似的任何使得这个任务太容易。任何能够正确处理标点符号的答案都会很棒。
示例:
给出字符串:"我喜欢巧克力"
返回字符串应该是:"我evol etalocohc"
为清楚起见,当我说正确处理标点符号时,我的意思是标点符号不应移动。
// reverse the letters of every word in a sentence (string), and return the result
public static String reverse(String x)
{
String[] str = x.split(" ");
StringBuilder rev = new StringBuilder("");
for (int i = 0; i < str.length; i++)
{
for (int s = str[i].length()-1; s >= 0; s--)
{
rev.append(str[i].charAt(s));
}
rev.append(" ");
}
return rev.toString();
}
这是我的一些测试的输出:
public static void main(String[] args)
{
System.out.println(reverse("I love chocolate"));//this passes
System.out.println(reverse("Geeks for Geeks"));//this passes
System.out.println(reverse("You, are awesome"));//not handling puncutation mark correctly, gives me ",uoY era emosewa", instead of "uoY, era emosewa"
System.out.println(reverse("Geeks! for Geeks."));//not handling puncutation marks correctly, gives me "!skeeG rof .skeeG", instead of "skeeG! rof skeeG."
}
答案 0 :(得分:1)
这可能适用于标点符号:
public static String reverse(String x)
{
String[] str = x.split("\\W"); //Split on non-word characters.
StringBuilder rev = new StringBuilder("");
int currentPosition = 0;
for (int i = 0; i < str.length; i++)
{
for (int s = str[i].length()-1; s >= 0; s--)
{
rev.append(str[i].charAt(s));
currentPosition++;
}
while (currentPosition < x.length() && Character.toString(x.charAt(currentPosition)).matches("\\W"))
rev.append(x.charAt(currentPosition++)); //Add the actual character there.
}
return rev.toString();
}
Haven现在用Java编写了一段时间,所以我知道这可能不是最好的做法。
复杂性是O(n)(空间和时间)。
如果您从字符串构建器开始,您可以通过使用就地字符交换而不是附加来降低空间复杂性,但是您需要抢先找到所有非字字符的位置。< / p>
答案 1 :(得分:1)
这是一种使用仅需要O(1)
存储的单词的就地反转的实现。此外,反转算法本身为O(N)
,其长度为字符串。
基本算法是沿着弦向下走,直到撞到一个空格。然后,调用swap()
方法来反转该特定单词。它只需要一个额外的角色。
由于大量使用StringBuilder
操作,这种方法可能不如接受的答案那样高效。但是,在像Android应用程序这样空间非常宝贵的环境中,这可能需要考虑。
public static void swap(StringBuilder input, int start, int end) {
for (int i=0; i <= (end - start) / 2; ++i) {
char ch = input.charAt(start + i);
input.setCharAt(start + i, input.charAt(end - i));
input.setCharAt(end - i, ch);
}
}
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("I love chocolate");
int start = 0;
int end = 0;
while (true) {
while (end <= sb.length() - 1 && sb.charAt(end) != ' ') {
++end;
}
swap(sb, start, end - 1);
start = end + 1;
end = start;
if (end > sb.length() - 1) {
break;
}
}
System.out.println(sb);
}
在这里演示:
答案 2 :(得分:1)
我刚刚更改了代码,而不是其他方法或循环,只是一些变量和条件。
/* Soner - The methods reverse a string with preserving punctiations */
public static String reverse(String x) {
String[] str = x.split(" ");
boolean flag = false;
int lastCharPosition;
StringBuilder rev = new StringBuilder("");
for (int i = 0; i < str.length; i++) {
flag = false;
lastCharPosition = str[i].length()-1;
if (str[i].charAt(lastCharPosition) == '.' || str[i].charAt(lastCharPosition) == '!'
|| str[i].charAt(lastCharPosition) == ',') { // you can add new punctiations
flag = true;
lastCharPosition = str[i].length()-2;
}
for (int s = lastCharPosition; s >= 0; s--) {
rev.append(str[i].charAt(s));
}
if (flag) rev.append(str[i].charAt(lastCharPosition + 1));
rev.append(" ");
}
return rev.toString();
}
答案 3 :(得分:1)
紧凑型解决方案
public static String reverse(String x) {
Matcher m = Pattern.compile("\\w+").matcher(x);
if(!m.find()) return x;
StringBuffer target = new StringBuffer(x.length());
do m.appendReplacement(target, new StringBuilder(m.group()).reverse().toString());
while(m.find());
return m.appendTail(target).toString();
}
Matcher
上的appendReplacement
循环+ appendTail
是等效于String.replaceAll(regex)
的手册,旨在支持替换比简单字符串更复杂的情况使用占位符,例如反转找到的单词。
不幸的是,我们必须在这里使用过时的StringBuffer
,因为API早于StringBuilder
。 Java 9 is going to change that
可能更有效的替代方案是
public static String reverse(String x) {
Matcher m = Pattern.compile("\\w+").matcher(x);
if(!m.find()) return x;
StringBuilder target = new StringBuilder(x.length());
int last=0;
do {
int s = m.start(), e = m.end();
target.append(x, last, s).append(new StringBuilder(e-s).append(x, s, e).reverse());
last = e;
}
while(m.find());
return target.append(x, last, x.length()).toString();
}
这在整个操作中使用StringBuilder
并使用该功能附加部分字符序列,而不是为匹配和替换创建中间字符串。它也没有在替换中搜索占位符,appendReplacement
在内部进行。