LeetCode 680 验证回文字符串 Ⅱ 做题感悟
Posted swsbty
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 680 验证回文字符串 Ⅱ 做题感悟相关的知识,希望对你有一定的参考价值。
leetcode-cn.com/problems/valid-palindrome-ii/
做题有感:
图2是最快写出来的暴力枚举(我写的时候都不知道自己写的是什么算法),手生,实际也花了好几分钟时间。
不出意外,超长字符串测试的时候超时了。
暴力枚举:
1 package com.company; 2 3 public class Daily680Tolerance { 4 5 public static boolean validPalindrome(String s) { 6 boolean r = judgeBackText(s); // 先比较以下字符串是否是回文字 7 if (r) { 8 return true; 9 } 10 for (int i = 0;i < s.length();i++) { 11 if (judgeBackText(removeChar(s, i))) { 12 return true; 13 } 14 } 15 return false; 16 } 17 18 /* 19 判断一段字符串是否是回文字的方法,采取比较 i和 length-i-1 下标位置的字符是否不相等的办法, 20 默认返回值是true,代表这段文字是回文字, 21 for循环进行比较,如果发现不相等就打破循环返回false 22 */ 23 private static boolean judgeBackText(String s) { 24 for (int i = 0;i < s.length() / 2;i++) { 25 if (s.charAt(i) != s.charAt(s.length() - 1 - i)) { 26 return false; 27 } 28 } 29 return true; 30 } 31 32 /* 33 删掉字符串中指定位置的字符,然后返回新的字符串。 34 采用substring的方法截断字符串,重新合并后再返回。 35 */ 36 private static String removeChar(String s, int index) { 37 if (index == 0) { 38 return s.substring(1); 39 } 40 if (index == s.length() - 1) { 41 return s.substring(0, s.length() - 1); 42 } 43 String tempFrontPart = s.substring(0, index); // 前半部分,不包括index位置的字符 44 String tempBehindPart = s.substring(index + 1); // 后半部分,不包括index位置的字符 45 return tempFrontPart + tempBehindPart; // 合并后返回 46 } 47 48 }
后来借鉴一下官方的解答(具体算法实现没看,只看了视频中两个算法的说明),又翻看了一下算法书中有关贪婪算法的解释,花了近一个小时的
时间,终于让我码出来了……
贪心算法:
1 package com.company; 2 3 public class Daily680Greedy { 4 5 public static boolean validPalindrome(String s) { 6 greedy(s, false); // 先递归 7 return result; // 返回最终结果 8 } 9 10 /** 11 * 算法思想:贪婪算法现学现用, 12 * 循环低位高位下标比较,如果相等就各向中间靠近一位, 13 * 不相等就打破循环,判断循环是否是正常结束,如果正常结束就将最终结果改为true, 14 * 如果不是正常结束,就判断是否进行过减去一个字符的操作,如果进行过,就结束, 15 * 如果没有进行过减去一个字符的操作, 16 * 分别进行字符串减去低位下标字符后的递归和减去高位下标字符后的递归, 17 * 同时将判断是否进行过减去一个字符的操作设为true, 18 * 等到方法都结束了,此时的result就是正确结果。 19 */ 20 private static boolean result = false; // 最终结果 21 private static void greedy(String s, boolean isMinusOne) { 22 int low = 0; // 低位下标 23 int high = s.length() - 1; // 高位下标 24 while (low < high) { 25 if (s.charAt(low) == s.charAt(high)) { // 如果低高位下标字符相等 26 low++; // 低位进一 27 high--; // 高位减一,也就是去掉这两个相等的字符 28 } else { // 如果不相等就打破循环 29 break; 30 } 31 } 32 if (low < high) { // 如果循环不是正常结束 33 if (!isMinusOne) { // 没有执行过减一字符操作 34 greedy(s.substring(low + 1, high + 1), true); // 减去低位字符后递归 35 greedy(s.substring(low, high), true); // 减去高位字符后递归 36 } 37 } else { // 正常结束,字符串s是回文字 38 result = true; 39 } 40 } 41 42 }
通过这道题,我感觉自己最大的问题,还是在于不理解方法在递归时方法内的代码是怎么执行的。
通过这道题,我才真正认识到需要递归调用的方法是不应该设置返回值的。
疑问:如果这道题用C写枚举,会超时吗?
以上是关于LeetCode 680 验证回文字符串 Ⅱ 做题感悟的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode 125. 验证回文串 && 680. 验证回文字符串 Ⅱ
LeetCode 680. 验证回文字符串 Ⅱ [Valid Palindrome II (Easy)]