5. 最长回文子串

给你一个字符串 s,找到 s 中最长的回文子串。


示例 1:

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:

输入:s = "cbbd"
输出:"bb"
示例 3:

输入:s = "a"
输出:"a"
示例 4:

输入:s = "ac"
输出:"a"

方案一:暴力解法(psleetcode会超时)

function isPalindrome($str) {
    return $str == strrev($str);
}

/**
 * @param String $s
 * @return String
 */
function longestPalindrome1($s) {
    if ($this->isPalindrome($s)) {
        return $s;
    }

    $len = strlen($s);

    $res = [];
    for ($i=0;$i<$len;$i++) {
        for ($j=1;$j<=$len;$j++) {
            $str = substr($s, $i, $j);
            if ($this->isPalindrome($str)) {
                $res[] = $str;
                $res = array_unique($res);
            }
        }
    }

    $max = 0;
    foreach ($res as $key => $item) {
        if (strlen($item) > strlen($res[$max])) {
            $max = $key;
        }
    }

    return $res[$max];
}

方案二:

function get_max_palindrome1($str)
    {
        $len = strlen($str);
        $res = [];// 结果数组
        $res2= [];// 偶数长度的结果
        // 使用array_unshift的目的是为了从前向数组插入每一次找到的答案。也可以直接更新单个元素数组,就是只要当前取到的字符串比原来的长,就把原来的覆盖掉
        // 使用多维数组不是必须的,以为数组或者变量也可以。这里就是做一个简单的记录,可以微调一下,多完成另一个功能
        array_unshift($res, $str[0]);// 默认将第一个字符作为最长回文串写入数组
        array_unshift($res2, '');// 默认一个空字符串,长度为0,初始化

        for ($i = 1; $i < $len ; $i++) {// 从第二个开始操作,因为第一个左边没有字符,只能算本身长度为1的回文串
            // 针对奇数长度的最长回文串
            $left = $right = $i;// 从中间向两边扩展,默认起始位置为中间的这个位置
            $tmp = $str[$i];// 临时回文串,用于中间数据处理,默认是当前字符串
            while ($left > 0 and $right < $len - 1) {// 限定,只要有任何一边到头,循环结束
                $left--;// 左边向左扩展
                $right++;// 右边向👉扩展
                if ($str[$left] == $str[$right]) {// 如果扩展以后左右相等,说明当前是回文串
                    $tmp = $str[$left] . $tmp . $str[$right];// 将当前符合的回文串组合在一起
                    if (strlen($tmp) > strlen($res[0])) {// 如果当前得到的回文串比原来数组中最长的回文串长,则记录该回文串信息
                        array_unshift($res, $tmp);// 将当前回文串信息(长度和内容)记录在结果数组中
                    }
                } else {// 不相等,就不用处理后续了,跳出循环
                    break;
                }
            }
            // 针对偶数长度的最长回文串
            $left2 = $i - 1;
            $right2 = $i;// 从中间向两边扩展,默认起始位置为中间的这个位置
            if ($str[$i] == $str[$i-1]) {// 如果当前的字符和他前一个字符相等,说明很可能是一个偶数长度的回文串
                $tmp2 = $str[$i-1] . $str[$i];// 两个拼一起,记录下来作为初始字符串
                if (count($res2) == 1) {// 如果只有一个,说明是只有一个默认的无效的元素
                    array_unshift($res2, $tmp2);// 相当于真正有效的第一个偶数长度的字符串
                }
                while ($left2 > 0 and $right2 < $len - 1) {
                    $left2--;
                    $right2++;

                    if ($str[$left2] == $str[$right2]) {// 如果扩展以后左右相等,说明当前是回文串
                        $tmp2 = $str[$left2] . $tmp2 . $str[$right2];// 将当前符合的回文串组合在一起
                        if (strlen($tmp2) > strlen($res2[0])) {// 如果当前得到的回文串比原来数组中最长的回文串长,则记录该回文串信息
                            array_unshift($res2, $tmp2);// 将当前回文串信息(长度和内容)记录在结果数组中
                        }
                    } else {// 不相等,就不用处理后续了,跳出循环
                        break;
                    }
                }
            }
        }

        // 结果数组中,第一个元素就是str是最长的回文串,谁长就返回谁
        if (strlen($res[0]) >= strlen($res2[0])) {
            return $res[0];// 奇数长度回文数组
        } else {
            return $res2[0];// 偶数长度回文数组
        }
    }

    function longestPalindrome($s) {
        $len = strlen($s);

        $res = []; // 结果数组
        $res2= [];// 偶数长度的结果

        // 使用array_unshift的目的是为了从前向数组插入每一次找到的答案。也可以直接更新单个元素数组,就是只要当前取到的字符串比原来的长,就把原来的覆盖掉
        // 使用多维数组不是必须的,以为数组或者变量也可以。这里就是做一个简单的记录,可以微调一下,多完成另一个功能
        array_unshift($res, $s[0]);// 默认将第一个字符作为最长回文串写入数组
        array_unshift($res2, '');// 默认一个空字符串,长度为0,初始化

        for ($i = 1; $i < $len; $i++) {// 从第二个开始操作,因为第一个左边没有字符,只能算本身长度为1的回文串
            // 针对奇数长度的最长回文串 aba
            $left = $i;
            $right = $i;

            $tmp = $s[$i];
            while ($left > 0 && $right < $len-1) {
                $left--;
                $right++;
                if ($s[$left] == $s[$right]) {
                    $tmp = $s[$left] . $tmp . $s[$right];// 将当前符合的回文串组合在一起
                    if (strlen($tmp) > strlen($res[0])) {
                        array_unshift($res, $tmp);
                    }
                } else {
                    break;
                }
            }

            // 针对偶数长度的最长回文串
            $left2 = $i - 1;
            $right2 = $i;// 从中间向两边扩展,默认起始位置为中间的这个位置

            if ($s[$left2] == $s[$right2]) {
                $tmp2 = $s[$left2] . $s[$right2];
                if (count($res2) == 1) {// 如果只有一个,说明是只有一个默认的无效的元素
                    array_unshift($res2, $tmp2);// 相当于真正有效的第一个偶数长度的字符串
                }
                while ($left2 > 0 && $right2 < $len-1) {
                    $left2--;
                    $right2++;
                    if ($s[$left2] == $s[$right2]) {
                        $tmp2 = $s[$left2] . $tmp2 . $s[$right2];
                        if (strlen($tmp2) > strlen($res[0])) {
                            array_unshift($res, $tmp2);
                        }
                    } else {
                        break;
                    }
                }
            }
        }
        return strlen($res[0]) >= strlen($res2[0]) ? $res[0] : $res2[0];
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值