leetcode valid-palindrome(Java)

leetcode题目

valid-palindrome – newcoder 26
验证回文字符串 – leetcode 125

题目描述

 * Given a string, determine if it is a palindrome, 
 * considering only alphanumeric(字母或数字) characters and ignoring cases.
 * For example,
 * "A man, a plan, a canal: Panama"is a palindrome.
 * "race a car"is not a palindrome.
 * 
 * Note: 
 * Have you consider that the string might be empty?
 *  This is a good question to ask during an interview.
 * 
 * For the purpose of this problem, we define empty string 
 * as valid palindrome. 

思路

 * 思路1:(首尾指针分别遍历到元素末尾和起始位置)
 * 1、使用双指针分别从字符串首尾开始遍历(需要先去除首尾非字母数字元素)
 * 2、如果是非字母、数字字符,则忽略,指针前移
 * 3、如果是字母数字,则比较两个指针指向的字符是否相同,不相同则返回false
 * 	 
 * 思路2:(首尾指针分别遍历,直到头指针i>=尾指针j)
 * 1、使用双指针分别从字符串首尾开始遍历(条件为i<j)
 * 2、如果是非字母、数字字符,则忽略,指针前移(i<j && xxx)
 * 3、如果是字母数字,则比较两个指针指向的字符是否相同,不相同
 *    则返回false(i<j && xxx)

代码

package com.leetcode.str;

import java.util.Arrays;
import java.util.regex.Pattern;

/**
 * 题目:
 * valid-palindrome -- newcoder 26
 * 验证回文字符串 -- leetcode 125
 * 
 * 题目描述:
 * Given a string, determine if it is a palindrome, 
 * considering only alphanumeric(字母或数字) characters and ignoring cases.
 * For example,
 * "A man, a plan, a canal: Panama"is a palindrome.
 * "race a car"is not a palindrome.
 * 
 * Note: 
 * Have you consider that the string might be empty? This is a good question to ask during an interview.
 * For the purpose of this problem, we define empty string as valid palindrome. 
 */
public class ValidPalindrome {

	/**
	 * 思路1:(首尾指针分别遍历到元素末尾和起始位置)
	 * 1、使用双指针分别从字符串首尾开始遍历(需要先去除首尾非字母数字元素)
	 * 2、如果是非字母、数字字符,则忽略,指针前移
	 * 3、如果是字母数字,则比较两个指针指向的字符是否相同,不相同则返回false
	 * 
	 */
    public boolean isPalindrome(String s) {
        if (s == null || s.length() <= 1) {
        	return true; 
        }
        
        char[] arr = s.toCharArray();

        // 去除首尾 非字母数字元素,避免下面遍历时指针越界
        arr = removeNoneAlphanumericChar(arr);
        if (arr == null || arr.length <= 1) {
        	return true;
        }
        
        int len = arr.length;
        
        // 首尾两个指针
        int start = 0;
        int end = len - 1;
        
        // 首尾指针同时遍历 
        while (start <= len - 1 || end >= 0) {
        	// 头指针遍历 直到遍历到是字母数字的char位置
        	while (!isAlphanumericChar(arr[start])) {
        		start++;
        	}
        	// 尾指针遍历 直到遍历到是字母数字的char位置
        	while(!isAlphanumericChar(arr[end])) {
        		end--;
        	}
        	
        	// 首尾指针指向元素 是否忽略大小写相等
        	if (arr[start] != arr[end] && Math.abs(arr[start] - arr[end]) != 32) {
        		return false;
        	}
        	
        	// 指针前移
    		start++;
    		end--;
        }
        
        return true;
    }
	
    private char[] removeNoneAlphanumericChar(char[] arr) {
    	int len = arr.length;
    	int start = 0;
    	int end = len - 1;
    	while (!isAlphanumericChar(arr[start])) {
    		start++;
    		// 全部为非数字字母
    		if (start >= len) {
    			return null;
    		}
    	}
    	while (!isAlphanumericChar(arr[end])) {
    		end--;
    		if (end < 0) {
    			return null;
    		}
    	}
    	return Arrays.copyOfRange(arr, start, end + 1);
    }
    
    private boolean isAlphanumericChar(char c) {
    	String regex = "[0-9a-zA-Z]{1}";
    	if (Pattern.matches(regex, String.valueOf(c))) {
    		return true;
    	}
    	return false;
    }
    
	/**
	 * 思路2:(首尾指针分别遍历,直到头指针i>=尾指针j)
	 * 1、使用双指针分别从字符串首尾开始遍历(条件为i<j)
	 * 2、如果是非字母、数字字符,则忽略,指针前移(i<j && xxx)
	 * 3、如果是字母数字,则比较两个指针指向的字符是否相同,不相同则返回false(i<j && xxx)
	 * 
	 */
    public boolean isPalindromeFast(String s) {
    	if (s == null || s.length() <= 1) {
    		return true;
    	}
    	int len = s.length();
    	char[] arr = s.toCharArray();
    	int i = 0;
    	int j = len - 1;
    	while (i < j) {
    		while (i<j && !isAlphanumericChar(arr[i])) {
    			i++;
    		}
    		while (i<j && !isAlphanumericChar(arr[j])) {
    			j--;
    		}
    		if (i<j && arr[i] != arr[j] && Math.abs(arr[i]-arr[j]) != 32) {
    			return false;
    		}
    		i++;
    		j--;
    	}
    	return true;
    }
    
	public static void main(String[] args) {
		System.out.println(new ValidPalindrome().isPalindrome("A man, a plan, a canal: Panama"));
		System.out.println(new ValidPalindrome().isPalindrome("race a car"));
		System.out.println(new ValidPalindrome().isPalindrome("a."));
		System.out.println(new ValidPalindrome().isPalindrome(".,"));
		
		System.out.println(new ValidPalindrome().isPalindromeFast("A man, a plan, a canal: Panama"));
		System.out.println(new ValidPalindrome().isPalindromeFast("race a car"));
		System.out.println(new ValidPalindrome().isPalindromeFast("a."));
		System.out.println(new ValidPalindrome().isPalindromeFast(".,"));
	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值