LeetCode初級算法之字符串:125 驗證迴文串

驗證迴文串

題目地址:https://leetcode-cn.com/problems/valid-palindrome/java

給定一個字符串,驗證它是不是迴文串,只考慮字母和數字字符,能夠忽略字母的大小寫。git

說明:本題中,咱們將空字符串定義爲有效的迴文串。數組

示例 1:數據結構

輸入: "A man, a plan, a canal: Panama"
輸出: trueapp

示例 2:學習

輸入: "race a car"
輸出: false優化

解法一:雙指針

首先判斷兩個字符串是不是迴文串,就是原串與倒序是否相等,那不就是前面寫的反轉字符串麼。只不過就是首尾交換,換成首尾是否相等。但在此以前咱們先要從原串中獲取數字字母串並忽略大小寫ui

public boolean isPalindrome(String s) {
    if(s == null || s.length() == 0) return true;
    char[] arr = s.toCharArray();
    int n = arr.length;
    StringBuilder cs = new StringBuilder();
    for (int i = 0; i < n; i++) {
        char c = arr[i];
        if (check(c)) {
            cs.append(change(c));
        }
    }
    n = cs.length();
    for(int i = 0; i < n/2; i++){
        if(cs.charAt(i) != cs.charAt(n-i-1)){
            return false;
        }
    }
    return true;
}
//是不是字母或數字
public boolean check(char c){
    return c>=48&&c<=57 || c>=65&&c<=90 || c>=97&&c<=122;
}
//大寫統一轉小寫
public char change(char c){
    return c>=65&&c<=90 ? c+=32 : c;
}

解法二:細節優化(雙指針)

咱們剛剛是用了兩個循環,第一個循環篩選了屬於字母數字的。第二次循環再判斷字母數字的串有木有重複。實際上是冗餘的,咱們直接在第一個循環完成便可,最終的目的是看字母數字是否迴文但不必取出來再作。那樣減小了一個容器和一次遍歷。指針

public boolean isPalindrome(String s) {
    if(s == null || s.length() == 0) return true;
    char[] arr = s.toCharArray();
    int n = arr.length;
    
    int start = 0;
    int end = n - 1;
    while(start < end){
        while(start < end && !check(arr[start])){
            start++;
        }
        while(start < end && !check(arr[end])){
            end--;
        }
        if(change(arr[start])!=change(arr[end])){
            return false;
        }
        start++;
        end--;
    }
    return true;
}
//是不是字母或數字
public boolean check(char c){
    return c>=48&&c<=57 || c>=65&&c<=90 || c>=97&&c<=122;
}
//大寫統一轉小寫
public char change(char c){
    return c>=65&&c<=90 ? c+=32 : c;
}

解法三:棧

雖然這題雙指針就是比較優的解法,可是前段時間學習了棧,所以在這題上用上溫習一下不過空間和效率應該是最低的,咱們都知道棧是後進先出(LIFO)一種數據結構。這裏咱們能夠用數組實現一下棧完成一下基本的四個方法code

class Stack<E>{
    List<E> arr = new ArrayList();
    int top = -1;        
    void push(E c){
        arr.add(++top,c);
    }
    E pop(){
        E c = peek();
        arr.remove(top--);
        return c;
    }
    E peek(){
        return arr.get(top);
    }
    boolean isEmpty(){
        return top < 0;
    }
}
public boolean isPalindrome(String s) {
    if(s == null || s.length() == 0) return true;
    char[] arr = s.toCharArray();
    int n = arr.length;
    Stack<Character> stack = new Stack<>();
    List<Character> list = new ArrayList<>();
        
    for (int i = 0; i < n; i++) {
        char c = arr[i];
        if (check(c)){
            stack.push(change(c));
            list.add(change(c));
        }
    }
    int index = 0;
    while (!stack.isEmpty()){
        if (stack.pop() != list.get(index++))
            return false;
    }
    return true;
}

總結

迴文串處理的大致方式仍是雙指針、反轉或者棧。對於此題Character類中提供了判斷是否爲數字或字母的方法和轉大小寫的方法。我上面是單獨寫的check(char c)與change(char c)方法。

isLetterOrDigit(char c)
toLowerCase(char c)

利用Java類庫的話直接有反轉方法固然它裏面也是一次遍歷處理,反轉再比較。固然效率是比較低的能夠參考

//cs爲取出來的只含字母數字的字符串
String fz = cs.reverse().toString();
return cs.equals(fz);

整體來講呢能夠實現的方式有不少,關注實現自己效率來講雙指針是較優的。

相關文章
相關標籤/搜索