1. 程式人生 > >LeetCode演算法題-Valid Palindrome(Java實現)

LeetCode演算法題-Valid Palindrome(Java實現)

這是悅樂書的第174次更新,第176篇原創

01 看題和準備

今天介紹的是LeetCode演算法題中Easy級別的第33題(順位題號是125)。給定一個字串,確定它是否是迴文,只考慮字母數字字元並忽略大小寫。空字串是有效迴文。例如:

輸入:“A man, a plan, a canal: Panama”
輸出:true

輸入:“race a car”
輸出:false

本次解題使用的開發工具是eclipse,jdk使用的版本是1.8,環境是win7 64位系統,使用Java語言編寫和測試。

02 第一種解法

特殊情況一:當傳入的字串為null時,直接返回true。

特殊情況二:當傳入的字串去掉空格後的長度為0時,直接返回true。

正常情況:因為傳入的字串可能包含特殊字元,如空格、","、":"、"?"等,這些都是非字母、數字字元,這對我們的判斷增加了難度,但是其核心思想是不變的。

首先可以將字串全部轉為小寫,然後建立兩個索引,一個從前往後,一個從後往前,依次獲取相應的字元,在判斷是否相等前,先要判斷獲取到的字元是否是字母、數字,不是字母和數字,索引向前移動一位,否則判斷兩個字元是否相等,不等於直接返回false,如果等於,索引向前移動一位,繼續迴圈,直到遍歷完判斷完所有的字元。

public boolean isPalindrome(String s) {
    if (s == null || s.trim().length() == 0) {
        return true;
    }
    s = s.toLowerCase();
    int left = 0;
    int right = s.length() - 1;
    while (left <= right) {
        Character c1 = s.charAt(left);
        Character c2 = s.charAt(right);
        if (!isAlphaNumeric(c1)) {
            left++;
        }else if (!isAlphaNumeric(c2)) {
            right--;
        } else {
            if (c1 != c2) {
                return false;
            }
            left++;
            right--;
        }
    }
    return true;
}

public static boolean isAlphaNumeric(Character c){
    if (c >= 'a' && c<= 'z') {
        return true;
    }
    if (c >= 'A' && c<= 'Z') {
        return true;
    }
    if (c >= '0' && c<= '9') {
        return true;
    }
    return false;
}

03 第二種解法

此解法和第一種解法思路一樣,但是藉助了Character.isLetterOrDigit()方法來幫我們判斷獲取到的字元是否為字母或者數字。

public boolean isPalindrome2(String s) {
    if (s == null || s.trim().length() == 0) {
        return true;
    }
    s = s.toLowerCase();
    int left = 0;
    int right = s.length() - 1;
    while (left <= right) {
        Character c1 = s.charAt(left);
        Character c2 = s.charAt(right);
        if (!Character.isLetterOrDigit(c1)) {
            left++;
        } else if (!Character.isLetterOrDigit(c2)) {
            right--;
        } else {
            if (c1 != c2) {
                return false;
            } 
            left++;
            right--;
        }
    }
    return true;
}

04 另類的解法

此解法不那麼正規,利用字串本身的一些方法以及StringBuffer類的reverse()方法來完成判斷。先將傳入的字串轉為小寫,並且去掉空格,然後利用正則,將非字母、數字的其他字元全部替換掉,再利用StringBuffer的reverse()方法,最後判斷兩字串是否相等。

public boolean isPalindrome3(String s) {
    if (s == null || s.trim().length() == 0) {
        return true;
    }
    String newString = s.toLowerCase().replace(" ", "").replaceAll("\\W", "");
    String newString2 = new StringBuffer(newString).reverse().toString();
    return newString.equals(newString2);
}

05 測試與驗證

對於上面三種方法,編寫了部分測試程式碼,如下:

public static void main(String[] args) {
    Easy_125_ValidPalindrome instance = new Easy_125_ValidPalindrome();
    String arg = "A man, a plan, a canal: Panama";
    long start = System.nanoTime();
    boolean result = instance.isPalindrome(arg);
    long end = System.nanoTime();
    System.out.println("isPalindrome---輸入:"+arg+" , 輸出:"+result+" , 用時:"+(end-start)/1000+"微秒");

    long start2 = System.nanoTime();
    boolean result2 = instance.isPalindrome2(arg);
    long end2 = System.nanoTime();
    System.out.println("isPalindrome2---輸入:"+arg+" , 輸出:"+result2+" , 用時:"+(end2-start2)/1000+"微秒");

    long start3 = System.nanoTime();
    boolean result3 = instance.isPalindrome3(arg);
    long end3 = System.nanoTime();
    System.out.println("isPalindrome3---輸入:"+arg+" , 輸出:"+result3+" , 用時:"+(end3-start3)/1000+"微秒");
}

測試結果如下:

isPalindrome---輸入:A man, a plan, a canal: Panama , 輸出:false , 用時:191微秒
isPalindrome2---輸入:A man, a plan, a canal: Panama , 輸出:true , 用時:27微秒
isPalindrome3---輸入:A man, a plan, a canal: Panama , 輸出:true , 用時:1566微秒

06 小結

此三種解法中最優的是解法二,最差的是解法三,如果筆試或者面試碰到此類題,以第二種解法作答較好。

以上就是全部內容,如果大家有什麼好的解法思路、建議或者其他問題,可以下方留言交流,點贊、留言、轉發就是對我最大的回報和支援!