【问题标题】:Reverse a string in Java, in O(1)?在 O(1) 中反转 Java 中的字符串?
【发布时间】:2010-06-24 12:31:01
【问题描述】:

在给定 CharSequence 的情况下,标准 Java 库中是否有任何工具可以在 O(1) 时间内产生相反的结果?

我想这很容易实现,只是想知道它是否已经存在。 (我怀疑不提供此功能的原因是因为“简单”的方法实际上会破坏多字符代码点 - 但在许多情况下,我们知道我们没有处理这些)。

谢谢

更新 呵呵,大多数人都认为这是“不可能的”,这有点有趣,伙计们!好吧,实际上它(在概念上)是微不足道的——为了清楚起见,pseudojava 如下:

class MyReverseString extends String { //of course I can't extend String!
   final String delegate;
   MyReverseString(String delegate) { this.delegate = delegate; }

   int length() { return delegate.length(); }

   int charAt(int i) { return delegate.charAt(delegate.length() - 1 - i); }
}

我将这个问题留待更多时间,只是在极少数情况下,JDK 中已经存在类似显而易见的解决方案(例如,参见 Jon Skeet 的解决方案)并且有人知道它。 (同样,由于那些讨厌的代码点,可能性很小)。

编辑 可能混淆来自于我在标题中有“字符串”(但不是字符串!),而我只要求“CharSequence 的反面”。如果您感到困惑,对不起。我希望 O(1) 部分能够准确地说明所要求的内容。

顺便说一句,this was the question that made me ask this one。 (在这种情况下,从右到左而不是从左到右运行正则表达式会更容易,因此即使对于简单/损坏的代码点实现也可能有一些实用价值)

【问题讨论】:

  • 如何在 O(1) 中反转字符串?您必须遍历字符串,对吗?下限肯定是 O(n)?
  • O(1)?将显示器旋转 180 度。
  • O(1) 并不意味着在您的代码中,您只需一行代码就可以完成任务,而无需循环......无论如何,StringBuffer() 解决方案似乎在这里最可行。跨度>
  • 也许你的意思是 O(1) 空间 - 如果是这样,你会使用 for 循环从 i=0..n/2 循环到从 i=0..n/2 交换字符 i 和长度-i,没有额外的内存已使用,并且更改了原始字符串。

标签: java string


【解决方案1】:

好吧,您可以轻松生成CharSequence 的实现,它返回相同的长度,并且当要求输入特定字符时,返回length-index-1 处的字符。 toString() 当然会变成 O(n)...

创建 反转 CharSequence 将是 O(1) - 毕竟它所要做的就是存储对原始 CharSequence 的引用。显然,迭代序列中的所有字符将是 O(n)。

请注意,创建反向 CharSequence(根据您的问题的正文)与创建反向 String(根据 标题你的问题)。实际上产生字符串是 O(n),而且必须是。

示例代码,大部分未经测试:

public final class ReverseCharSequence implements CharSequence
{
    private final CharSequence original;

    public ReverseCharSequence(CharSequence original)
    {
        this.original = original;
    }

    public int length()
    {
        return original.length();
    }

    public char charAt(int index)
    {
        return original.charAt(original.length() - index - 1);
    }

    public CharSequence subSequence(int start, int end)
    {
        int originalEnd = original.length() - start;
        int originalStart = original.length() - end;
        return new ReverseCharSequence(
            original.subSequence(originalStart, originalEnd));
    }

    public String toString()
    {
        return new StringBuilder(this).toString();
    }
}

【讨论】:

  • 在收藏术语中,我认为您称其为“视图”,对吗?您当然可以在 O(1) 中创建 CharSequence 的反向“视图”,这就是您在此处显示的内容。
  • @polygenelubricants:是的,没错。根据需要,该视图本身就是一个 CharSequence。如果OP希望特定操作为O(1),他应该澄清:)
  • 我明白你在做什么,但我怀疑这个实现是否会在恒定时间内完成他想要它做的事情。
  • @Justin:没有进一步的信息,我认为这与他将得到的差不多。构造肯定是 O(1),如果在底层实现中,除了 toString() 之外的任何东西也是 O(1)。
  • 当然不用担心。您可能会在上面看到触发我搜索 O(1) 字符串反转的原始问题/问题(好的,好的,不是“字符串”!“CharSequence”!)。
【解决方案2】:

这是不可能的。为了反转一个字符串,您必须至少处理每个字符一次,因此,它必须至少是O(n)

【讨论】:

  • 如果反对者真的认为这是可能的,请告诉我怎么做。
  • 不......反对者认为简单地说“这是不可能的”不是一个有用的答案。但是,在编辑之后,这个人的想法正好相反(所以赞成);-)
  • @Justin: “我从来没想过这样” 在发布你的答案的第一个版本之前,确保它是有帮助的,即使你打算回来改进它。否则,有什么办法阻止人们只是发布“alsdfkjalsdkjflaskdfj”然后对其进行编辑,以抢占杆位?
  • @Justin:然而,显然人们并不认为它有帮助。不是在这里寻找论点,而是发布无用的答案以“先到达那里”然后再返回编辑只是不正确地坐在那里。我的意思是,键入“为了反转一个字符串,您必须至少处理每个字符一次,因此,它必须至少是O(n)”需要多长时间。也一样?
  • @Justin,不过,如果您事先知道这不是您的最终答案,为什么要发布它?其他人怎么会知道这不是你的最终答案?对于这样的答案,如果得到(或更多)反对票,请不要感到惊讶。
【解决方案3】:
string result = new StringBuffer(yourString).reverse().toString();

根据您在 O(1) 下的理解,这似乎是不可能的,因为即使读取字符串一次也需要 O(n),其中 n 是字符串中的字符数。

【讨论】:

    【解决方案4】:

    StringBuffer 有一个反转:http://java.sun.com/j2se/1.4.2/docs/api/java/lang/StringBuffer.html#reverse()

    顺便说一句,我假设您的意思是 O(n),因为 O(1)(正如其他人提到的)显然是不可能的。

    【讨论】:

      【解决方案5】:

      所有其他人都已经写过,这在 O(1) 时间内是不可能的,因为您必须至少查看每个字符一次。

      但是,如果您的意思是如何在 O(1) 空间中执行此操作,则如下:如果您想在 O(1) 空间中执行此操作,您显然不能分配相同长度的新字符串,但是您有就地交换字符。

      所以你所要做的就是从左到中迭代字符串,同时从右到中并交换元素。伪代码(约定:让字符串s 可以通过s[n]n-th 字符处访问。如果s 的长度为k,我们说它有元素0k-1):

      for i=0; i<len(s)/2; ++i{
       char tmp = s[i]
       s[i] = s[len(s)-1-i]
       s[len(s)-1-i] = tmp
      }
      

      所以你看,你所需要的只是一个辅助变量tmp,其中包含你当前用于交换它的字符,所以你可以在 O(1) 空间内完成它。

      【讨论】:

        【解决方案6】:

        Jon Skeet 的解决方案可能是最有效的。但是如果你只是想要一个快速和肮脏的,这应该可以做到,我认为它在性能上不会落后。

        StringBuffer reverse=new StringBuffer(original.toString()).reverse();
        

        StringBuffer 是一个 CharSequence,所以如果您暗示结果必须是一个 CharSequence,那么就是这样。

        好吧,如果您多次检查序列,这可能比 Skeet 先生的解决方案更快,因为它消除了每次读取字符时找到正确字符位置的计算开销。每个角色只执行一次。

        如果我要做十亿个这样的事情,也许我会做一个基准测试。

        【讨论】:

          【解决方案7】:

          最好还是用StringBuilder来反转,就是StringBuffer的非同步版本。

          【讨论】:

            【解决方案8】:
            for (count = str.length()-1; count >= 0; count--) {
                 tempStr = tempStr.concat(Character.toString(origStr.charAt(count)));
            }
            

            【讨论】:

              【解决方案9】:

              这里我有一个使用子字符串方法和 o(n) 的相同示例。我知道使用子字符串将保存完整的字符串内存。

              for(int i = 0; i < s.length(); i++)    {
                  s = s.substring(1, s.length() - i) + s.charAt(0) + s.substring(s.length() - i);
                  System.out.println(s);
              }
              

              这可能会对您有所帮助。如果我错了,请告诉我!

              【讨论】:

                【解决方案10】:

                //努力解决这个问题

                public static String ReverseString(String s){
                    if (s.length()>0){
                        s=s.charAt(s.length()-1)+printString(s.substring(0,s.length()-1));
                    }
                    return s;
                }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2021-02-13
                  • 2011-11-26
                  • 1970-01-01
                  • 2020-06-25
                  • 1970-01-01
                  • 2017-01-28
                  • 1970-01-01
                  • 2021-04-28
                  相关资源
                  最近更新 更多