【leetCode】leetCode125 Valid Palindrome

it2022-05-08  8

(如果想查看最终代码,直接跳到最后,如果想看中间踩过的坑,可以看看过程)

题目如下:

Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. Note: For the purpose of this problem, we define empty string as valid palindrome. Example 1: Input: "A man, a plan, a canal: Panama" Output: true Example 2: Input: "race a car" Output: false

很容易想到用对撞指针,即给首尾各定义一个指针。碰到非数字和字母的元素,跳过,直到两个都是字母或者数字,进行比较。

错误一, 一开始忽略了数字(又是低级错误,没读懂数字字母的英文),所以提交后,0p(数字0,不是字母O)测试用例没通过。因为在我的代码里认为数字也是像符号一样可以忽略的。 后来改了判断范围,在本地以下代码通过

package collisionsPointer; public class ValidPalindrome125 { private static boolean isPalindrome (String s) { char[] chars = s.toCharArray(); int l=0; int r=chars.length-1; while(l<=r) { if(!((chars[l]>='0'&&chars[l]<='9')||(chars[l]>='a'&&chars[l]<='z')||(chars[l]>='A'&&chars[l]<='Z'))){ l++; continue; } if(!((chars[r]>='0'&&chars[r]<='9')||(chars[r]>='a'&&chars[r]<='z')||(chars[r]>='A'&&chars[r]<='Z'))) { r--; continue; } //都是字母了 if(chars[l] != chars[r] && chars[l]+32 != chars[r] && chars[l]-32 != chars[r] ) { return false; } else { //对应位置的字母相同,移动指针 l++; r--; } } return true; } public static void main(String[] args) { String s1 = "0p"; boolean res = isPalindrome(s1); System.out.println(res); } }

我为什么在自己的程序里没有直接取非法的范围,而是取到合法的范围然后取非,因为我假定此时并不知道各数字和字母ASCII码的范围(当然自己做题可以百度,假定此时不能百度),所以不好直接取非法的范围。 这个代码在本地{0p}能通过,但是提交到leetCode时,通不过.硬是将0P判断为ture,我也很无奈啊…

不过我发现了自己代码的另外一个bug : 判断两个字符是否相同或者为大小写的时候,直接用了比较两个字符的相等或者±32相等就认为是相同的,同样还是忽略的数字的问题,因为如果是大小写字母的话,这样判断没有问题,但是如果有数字,可能会出现数字的ASCII码+32与某一个字母的ASCII码一样,同样会判断错误。需要分开判断,所以虽然这个用例在本地侥幸判断正确的,但是代码其实是不完全正确的, 然后我就把代码改成了如下: 于是就出现了错误二:

char[] chars = s.toCharArray(); int l=0; int r=chars.length-1; while(l<r) { if(!((chars[l]>='0'&&chars[l]<='9')||(chars[l]>='a'&&chars[l]<='z')||(chars[l]>='A'&&chars[l]<='Z'))){ l++; continue; } if(!((chars[r]>='0'&&chars[r]<='9')||(chars[r]>='a'&&chars[r]<='z')||(chars[r]>='A'&&chars[r]<='Z'))) { r--; continue; } //都是字母数字了 //如果左边是数字,只比较大小 if((chars[l]>='0'&&chars[l]<='9')) { if(chars[l] != chars[r]) { return false; } } //如果左边是字母 else { //如果右边是数字,直接返回 if((chars[r]>='0'&&chars[r]<='9')) { return false; } //如果右边也是字母,可判断大小写相等 else { if(chars[l] != chars[r] && chars[l]+32 != chars[r] && chars[l]-32 != chars[r] ) { return false; } else { //对应位置的字母相同,移动指针 l++; r--; } } } } return true;

提交结果:在{1b1}用例时:超时…这个…抓狂啊!

最后,用了java库自带的转换为小写库,这样就省去了复杂的判断过程,战战兢兢地提交:accpted.

Runtime: 3 ms, faster than 96.33% of Java online submissions for Valid Palindrome. Memory Usage: 37.7 MB, less than 97.71% of Java online submissions for Valid Palindrome.

看百度有些人单独判断了空串或者只有一个字符的字符串,其实没必要,在while处都过不了,直接返回了true.

package collisionsPointer; public class ValidPalindrome125 { private static boolean isPalindrome (String s) { s=s.toLowerCase();//就不存在大小写的问题了,直接比较是否相等 char[] chars = s.toCharArray(); int l=0; int r=chars.length-1; while(l<r) { if(!((chars[l]>='0'&&chars[l]<='9')||(chars[l]>='a'&&chars[l]<='z')||(chars[l]>='A'&&chars[l]<='Z'))){ l++; continue; } if(!((chars[r]>='0'&&chars[r]<='9')||(chars[r]>='a'&&chars[r]<='z')||(chars[r]>='A'&&chars[r]<='Z'))) { r--; continue; } if(chars[l] != chars[r]) { return false; } else { //对应位置的字母相同,移动指针 l++; r--; } } return true; } public static void main(String[] args) { String s1 = "p212P"; boolean res = isPalindrome(s1); System.out.println(res); } }

最新回复(0)