美文网首页
“20200202”正好是一段“回文”,如何快速在一个字符串里找

“20200202”正好是一段“回文”,如何快速在一个字符串里找

作者: 郭亮_fa85 | 来源:发表于2020-02-03 08:23 被阅读0次

    昨天的日期很具有纪念意义,“20200202”正好是一段回文,很多朋友也在朋友圈记录了这有意义的一刻。
    那么什么是回文呢?就是从前往后,和从后往前完全一致的字符串,就是一段回文了。
    如果我们把回文隐藏在其他一段字符串中,例如“122320200202111”或者“202002029982”,能否用程序快速的找出它呢?
    正好leetcode上就有这么一个问题,我们来看看:

    1. Longest Palindromic Substring

    Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
    Example 1:
    Input: "babad"
    Output: "bab"
    Note: "aba" is also a valid answer.
    Example 2:
    Input: "cbbd"
    Output: "bb"

    此问题是需要找到一个字符串中长度最长的一段回文。
    思路如下:我们遍历整个字符串中的每个字符,假设指针a指向当前的字符,需要有两个分支判读:

    1. 例如“bb”这种回文,一个指针a指向当前字符,另一个指针b指向下一个字符;当a和b的值相等时a--,b++继续循环判断是否相等,直到不相等或者指针越界后中断。
    2. 例如“aba”这种回文,一个指针a-1指向当前字符的前一个字符,另一个指针b指向下一个字符;当a和b的值相等时a--,b++继续循环判断是否相等,直到不相等或者指针越界后中断。

    好了,这经过分析,这两种方法唯一的不同就是指针a的初始化值不同,那么我们可以提取公共的函数:

        int max = 0;
        String result = "";
    
        void scanMatched(String s, int j, int scanIndex) {
            while(j >=0 && scanIndex < s.length()) {
                if (s.charAt(j) == s.charAt(scanIndex)) {
                    j--;
                    scanIndex++;
                } else {
                    break;
                }
            }
            int matched = scanIndex - (j + 1);
            if (max < matched) {
                max = matched;
                result = s.substring(j + 1, scanIndex);
            }
        }
    

    此函数使用两个数组指针j和scanIndex,代表分析过程中的a和b进行运算,s就是原始的字符串。同时我们通过公共变量进行最大值的保存和判断。
    我们再来加上调用方法:

        public String longestPalindrome(String s) {
            if (s == null) {
                return "";
            }
            if (s.length() < 2) {
                return s;
            }
            if (s.length() == 2) {
                return s.charAt(0) == s.charAt(1) ? s : s.substring(0, 1);
            }
            
            for (int i = 0; i < s.length() - 1; i++) {
                int j = i - 1;
                int scanIndex = i + 1;
                scanMatched(s, j, scanIndex);
                scanMatched(s, i, scanIndex);
            }
            return result;
        }
    

    在这里我们加上了边界判断条件,以及之前分析的两个分支判读,分别进行调用,组装后完整的代码如下:

    class Solution {
        int max = 0;
        String result = "";
        
        public String longestPalindrome(String s) {
            if (s == null) {
                return "";
            }
            if (s.length() < 2) {
                return s;
            }
            if (s.length() == 2) {
                return s.charAt(0) == s.charAt(1) ? s : s.substring(0, 1);
            }
            
            for (int i = 0; i < s.length() - 1; i++) {
                int j = i - 1;
                int scanIndex = i + 1;
                scanMatched(s, j, scanIndex);
                scanMatched(s, i, scanIndex);
            }
            return result;
        }
        
        void scanMatched(String s, int j, int scanIndex) {
            while(j >=0 && scanIndex < s.length()) {
                if (s.charAt(j) == s.charAt(scanIndex)) {
                    j--;
                    scanIndex++;
                } else {
                    break;
                }
            }
            int matched = scanIndex - (j + 1);
            if (max < matched) {
                max = matched;
                result = s.substring(j + 1, scanIndex);
            }
        }
    }
    

    首先我们带入"122320200202111"进行测试,得到预期的返回:

    image.png
    我们再带入另一个分支的测试用例"ccbbbbda",依然成功:
    image.png
    最后提交代码,成绩马马虎虎吧_
    image.png
    这个空间复杂度是O(1),但是时间复杂度基本上是O(n^2)了,那么有没有更好的方式呢?嗯。。。留给读者来给我答案吧。

    相关文章

      网友评论

          本文标题:“20200202”正好是一段“回文”,如何快速在一个字符串里找

          本文链接:https://www.haomeiwen.com/subject/ttncxhtx.html