Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java isPalindrome()的时间复杂度O()_Java_Performance_Big O_Time Complexity - Fatal编程技术网

Java isPalindrome()的时间复杂度O()

Java isPalindrome()的时间复杂度O(),java,performance,big-o,time-complexity,Java,Performance,Big O,Time Complexity,我有这个方法,isPalindrome(),我试图找到它的时间复杂性,并更有效地重写代码 boolean isPalindrome(String s) { boolean bP = true; for(int i=0; i<s.length(); i++) { if(s.charAt(i) != s.charAt(s.length()-i-1)) { bP = false; } } return bP;

我有这个方法,isPalindrome(),我试图找到它的时间复杂性,并更有效地重写代码

boolean isPalindrome(String s) {
    boolean bP = true;
    for(int i=0; i<s.length(); i++) {
        if(s.charAt(i) != s.charAt(s.length()-i-1)) {
            bP = false;
        }
    }
    return bP;
}
boolean isPalindrome(字符串s){
布尔bP=true;

对于(inti=0;i第一个改进:一旦发现不匹配项,就可以中断,对吗?

它只是O(N)

说O(N+3)并没有真正的意义——常数因子被忽略了

当发现不匹配时,您可以通过中断来加快速度:

bP = false;
break;
(这并没有改变O(N)的事实,但在大多数情况下,它会加快速度。)

事实并非如此:

这段代码检查字符串的字符,看它是否与前面的字符相同

它检查开始处的字符是否与结束处的字符匹配,因此换句话说,它是一个幼稚的检查器

另一种加速方法是循环直到
s.length()/2
——否则对回文字符串进行两次比较。

是O(N)。进行N次比较,其中N=s.length()。每次比较都需要O(1)个时间,因为这是一个单字符比较


+3不重要,因为渐近表示法只关心最高阶项。

你可以在(i==(s.length()/2)+1处停止,将函数的复杂度减半。它与大O项无关,但它仍然是一个相当不错的增益。

复杂度总是没有代价(因为对于N->oo,它们并不重要)因此,您的时间复杂度只是
O(n)

另外,为了提高效率,将字符存储在临时字符串中是否好


这不是你的工作。JIT编译器将为你处理这个微优化。

那么首先,这个方法应该做什么

我的猜测是:确定一个字符串是否是一个字符串

很明显,在O(N)下,您将无法将其记录下来:

另一个问题是,这是最有效的解决方案吗?也许不是

有待改进的地方:

  • 把它切成两半。你检查所有字符两次(就像Michiel Buddingh建议的那样)

  • 事先获取字符数组。这样就省去了在
    chatAt()
    中进行的一些索引检查


  • 所有其他操作,
    charAt()
    length()
    ,在标准字符串实现中都是O(1)。

    假设循环中的操作可以在恒定时间内执行,复杂性为O(N)。
    由于“Big-O”表示法测量的是增长,而不是纯粹的速度,常数因子可以忽略不计。这就给我们留下了O(N+3)等于O(N)的结论。

    给定的代码似乎是通过检查字符“N”是否与字符“length-N”相同来检查字符串是否是回文.如前所述,您可以通过以下方式提高效率

    • 只检查上半场
    • 一旦发现不匹配项,立即爆发(返回false)
    除了这些建议,我还要补充一点

    • 不要每次通过循环都重复计算s.length(),因为它不会更改
    鉴于所有这些:

    boolean isP(String s) {
      int l = s.length();
      int l2 = l/2;
      int j = l - 1;
      for(int i=0; i<l2; i++) {
        if(s.charAt(i) != s.charAt(j)) {
            return false;
        }
        j--;
      }
      return true;
    }
    
    布尔isP(字符串s){
    int l=s.长度();
    int l2=1/2;
    int j=l-1;
    对于(int i=0;i这很可能是Java中最有效的实现:

    首先,上面的测量是使用客户端VM完成的。因此计算
    i<(chars.length/2)
    不是作为常量内联的。使用-server VM参数得到了更好的结果:

     Aran:           18756295
     Andreas:        15048560
     Paul Tomblin:   17187100
    
    让它变得有点极端:


    首先警告一句:不要在您打算使用/发布的任何程序中使用此代码


    正如评论中所指出的,它包含隐藏的bug,不遵守Java,也没有错误处理。它纯粹是为了证明通过肮脏的技巧可以获得的理论性能改进

    从字符串复制数组时会有一些开销,因为string类在内部进行防御复制

    如果我们直接从字符串中获取原始char[],我们可以挤出一点性能,但代价是对字符串使用反射和非保存操作。这将使我们获得另外20%的性能

    public static boolean isPReflect(String s) {
        char[] chars = null;
        try {
            final Field f = s.getClass().getDeclaredField("value");
            f.setAccessible(true);
            chars = (char[]) f.get(s);
        }
        catch (IllegalAccessException e) {
        }
        catch (NoSuchFieldException e) {
        }
    
        final int lenToMiddle = chars.length / 2;
        for (int i = 0; i < lenToMiddle; i++) {
            if (chars[i] != chars[(chars.length - i - 1)]) 
                return false;
        }
        return true;
    }
    

    首先,对于任意输入字符串,“最坏情况”复杂度比
    O(N)
    好的问题,不可能有单线程解决方案。简单地说,任何算法都必须在最坏情况下查看字符串中的每个字符。理论上,您可以改进
    O(N)
    使用硬件并行;即,在字符串的不同部分上工作的处理器数量可以无限扩展。实际上,很难实现任何加速。将输入字符串(或相关部分)发送到每个处理器的成本将为“O(N)”,除非有我不知道的解决办法

    第二,正如你可以看到的,<代码> o(n)< /代码>行为并不是最终的答案。你还需要考虑乘法常数为n>无穷大,而对于n/< 第三,@dfa说微优化不关你的事。他走的是对的,但我认为没有那么明确。在我看来,微优化是浪费时间,除非1)你的应用程序真的需要尽可能快地运行,2)您对应用程序的分析表明,这个特定的计算确实是一个重要的瓶颈

    最后,对于一个特定的硬件平台/JIT编译器来说,使程序更快的微优化可能会使另一个程序更慢。对于JIT编译器来说,复杂的微优化代码更难为其生成有效的代码。如果使用反射来访问(例如)的内部结构在String类中,您的代码实际上可能在某些平台上失败。(Java类库规范中没有说明字符串有一个名为“value”的私有字段,它是一个
    char[]
    !!!)

    下面是另一个解决方案
     Aran:           32244042
     Andreas:        60787894
     Paul Tomblin:   18387532
    
     Aran:           18756295
     Andreas:        15048560
     Paul Tomblin:   17187100
    
    public static boolean isPReflect(String s) {
        char[] chars = null;
        try {
            final Field f = s.getClass().getDeclaredField("value");
            f.setAccessible(true);
            chars = (char[]) f.get(s);
        }
        catch (IllegalAccessException e) {
        }
        catch (NoSuchFieldException e) {
        }
    
        final int lenToMiddle = chars.length / 2;
        for (int i = 0; i < lenToMiddle; i++) {
            if (chars[i] != chars[(chars.length - i - 1)]) 
                return false;
        }
        return true;
    }
    
     Aran:           18756295
     Andreas1:       15048560
     Andreas2:       12094554
     Paul Tomblin:   17187100
    
    boolean isPalindrome(String s) {
        int i = 0, j = s.length() - 1;
        while (i < j && s.charAt(i) == s.charAt(j)) {
            ++i;
            --j;
        }
        return i >= j;
    }
    
      4 + n/2 · (3 + 4) + 1
    = 5 + n/2 · 7
    = 5 + 7/2 · n
    
    def isPalindrome?(x)
     return x == x.reverse
    end