LeetCode No.5 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.

题目大意:给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。

Example 1:

Input: "babad"
Output: "bab"

Note: "aba" is also a valid answer.

Example 2:

Input: "cbbd"
Output: "bb"

The median is (2 + 3)/2 = 2.5

My solution(错误,没有考虑到”bccd”这种两两相邻的情况)

这道题难度中等,但是却卡了很长时间,主要出现了两个问题:一是编程时候出现没有考虑到”bccd”这种两个相邻的元素;二是做判断条件时候一个while循环做了所有判断,这个时候出现了列表索引超出范围现象。

class Solution:
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """

        radius = max_radius = temp = temp_two = key = 0

        if len(s) == 0 or len(s) == 1:
            return s

        for i in range(len(s)):
            for radius in range(i+1):                    
                if i - radius >= 0 and i + radius <= len(s) - 1 and s[i - radius] == s[i + radius]:
                    temp += 1
                else:
                    break

            if temp > max_radius and temp > temp_two:
                max_radius = temp
                key = i
            elif temp_two > max_radius and temp_two >= temp:
                max_radius = temp_two
                key = i
            temp = temp_two = 0


        return s[key - max_radius + 1:key + max_radius]

嗯~小伙伴感兴趣可以将代码提交试试看,只能通过部分样例测试。为什么呢?小詹提交后发现类似示例2“cbbd”这种会出错!找到了错误就好分析了,是因为上边的代码默认从同一个字符位置向两端拓展,然而类似“cbbd”这种测试用例,是从相邻两个字符串位置进行拓展,所以我们可以两种情况都考虑进去,最后选择最长的,考虑到这之间有相同的操作,为代码整洁,将其模块化分割出一个函数,代码如下:

Reference solution

仔细分析题目,nums1和nums2都已经是排好序了的,这就大大的降低了难度,让找到两个列表的中间值,其实我们可以拓展为找到两个列表的第k个值。当然这个是拓展部分了,对于这个题目,有不同的思路,最简单粗暴的就是将两个列表合并,之后进行排序,拍好序后进行寻找中间值就简单了。但是用传统的先合并再排序,效率想必会很低~

我们发现对于两个已经有序的列表(从小到大),其实有一个更优的排序方式:从小到大,依次进行列表元素的比较(为方便表述,称两个列表为A,B),较小值放到一个新列表中,比如A中该位置的值较小,将其放到新的列表C中,同时将A列表下一个值继续与B中当前位置元素进行比较,以此类推。

这样的比较次数就比先合并在排序小很多啦!代码如下:


class Solution:
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        #小詹提示:这种题要注意特例,单字符本身就是自己的最大回文子串噢        
        if len(s) < 2:
            return s
        #定义待返回的字符串
        self.res = ""
        for i in range(len(s)):
            #这里就是考虑到两种情况,从相同字符拓宽和从相邻字符拓宽
            self.helper(s, i, i)
            self.helper(s, i, i+1)
        return self.res

    #分割出来的相同操作函数! 
    def helper(self,s, left, right):
        #这里是判断当前回文子串两端相同的时候,向两端拓展
        while left>=0 and right < len(s) and s[left] == s[right]:
            left -= 1
            right += 1
            #这里的right-left-1是当前的回文子串长度,大于历史最大值,就更新最大值
        if right -left -1 > len(self.res):
            self.res = s[left+1:right]

给出运行结果之前,有必要关于self说几句,之前也有小伙伴群里问过,这里给出几句话:

  1. self 不是一个关键词,可以替换成其他(比如this),只是习惯用self

  2. self不是指向类本身,而是指向类实例对象(比如class person() a = person(‘xiaozhan’),这时self会指向实例person类的实例类对象a)

  3. 使用self.res是相当于定义一个类变量,这样在helper函数中也可以直接操作其他函数修改过的self.res,这个时候相当于类内方法都操作同一self.res。

猜你喜欢

转载自blog.csdn.net/Dby_freedom/article/details/82195021