簡體   English   中英

由於 String / StringBuilder Equality 的最長回文邊緣情況

[英]Longest Palindrome Edge Case due to String / StringBuilder Equality

此代碼不適用於測試用例: aacabdkacaa ,但適用於babadcbbd 我寫了一個打印語句來調試並意識到代碼認為字符串aacakdbacaaaacabdkacaa出於某種原因是等價的。 他們顯然不是,所以我錯過了什么?

class Solution {
    public String longestPalindrome(String s) {
        String longPal = "";
        for(int i = 0; i < s.length(); i++) {
            for(int j = s.length()-1; j >= i; j--) {
                if(s.charAt(i) == s.charAt(j)) {
                    StringBuilder sb = new StringBuilder(s.substring(i, j+1));
                    if(sb.reverse().toString().equals(sb.toString()) 
                       && sb.toString().length() > longPal.length()) {
                        longPal = sb.toString();
                        System.out.println(sb.toString()+" equals "+sb.reverse().toString());
                    }
                    sb.setLength(0);
                }
            }
        }
        return longPal;
    }
}

代碼不認為aacakdbacaaaacabdkacaa是相等的。

if語句中條件的第一部分是 this

sb.reverse().toString().equals(sb.toString())

所以代碼(JVM)認為這個條件是true 這是為什么? 這背后隱藏着什么知識(因為有一些)?

隱藏的知識部分(並不是真正隱藏,在文檔中)是StringBuilder reverse方法(實際上幾乎所有SB方法)改變了StringBuilder的state,通常返回StringBuilder實例本身。

所以對sb.reverse()的調用只是反轉 StringBuilder 實例的內容並返回實例本身(即相同的實例。),實例沒有改變。 只是它的內部 state 發生了變化。

然后我們對其調用toString() ,它返回當前 state 的String表示(如預期的那樣)。

然后我們在返回的String上調用equals並傳入equals sb.toString()作為第一個參數的值。 但是sb與一納秒前從sb.reverse()返回的實例相同。 它的 state 之間沒有改變,所以我們得到了從調用sb.toString()返回的相同String表示。

這就是為什么

sb.reverse().toString().equals(sb.toString())

是真的。

我們可以稍微不同地寫它,但仍然得到相同的結果

String s1 = sb.reverse().toString() // sb state changed here when .reverse() was called
String s2 = sb.toString()
s1.equals(s2) // true

如果我們使用,我們會得到不同的結果

String s1 = sb.toString()
String s2 = sb.reverse().toString() // sb state changed here
s1.equals(s2) // now it depends, true if palindrome, false otherwise!

所以這將是檢查回文的正確檢查

sb.toString().equals(sb.reverse().toString())

StringBuilder 的 reverse() 方法導致它的字符序列被序列的反向替換,因此 sb.reverse().toString().equals(sb.toString()) 總是結果為真。 聲明另一個字符串String p = sb.toString()然后用它來比較sb.reverse().toString().equals(p.toString())可以解決問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM