zoukankan      html  css  js  c++  java
  • 算法培训

    第一节

    最长回文子串

    给出一个字符串(假设长度最长为1000),求出它的最长回文子串,你可以假定只有一个满足条件的最长回文串。

    样例

    给出字符串 "abcdzdcab",它的最长回文子串为 "cdzdc"

    挑战

    O(n2) 时间复杂度的算法是可以接受的,如果你能用 O(n) 的算法那自然更好。

    我的n^3代码:

    class Solution:
        """
        @param s: input string
        @return: the longest palindromic substring
        """
        def longestPalindrome(self, s):
            # write your code here
            start, end = 0, 0
            for i in range(0, len(s)):
                for j in range(i, len(s)):
                    if (j-i)>(end-start) and self.isPalind(s, i, j):
                        start, end = i, j
            return s[start:end+1]
        
        def isPalind(self, s, i, j):
            while i<j:
                if s[i] != s[j]:
                    return False
                i += 1
                j -= 1
            return True
    

     从中心点左右遍历的解法,注意回文是奇偶情况,这才是这个题目的关键点:

    class Solution:
        """
        @param s: input string
        @return: the longest palindromic substring
        """
        def longestPalindrome(self, s):
            # write your code here
            start,end = 0,0
            n = len(s)
    
            def locatePalindrome(s, i, j):
                nonlocal start,end
                while i>=0 and j<n:
                    if s[i] == s[j]:
                        if end-start < j-i+1:
                            start,end = i,j+1
                    else:
                        break
                    i -= 1
                    j += 1
                    
            for i in range(n):
                # center i
                locatePalindrome(s, i, i)
                # center i,i+1
                locatePalindrome(s, i, i+1)
            return s[start:end]                        
    

    DP解法:细节有点多,不一定能够写对。。。尤其是那个for是从大到小递减。

    class Solution:
        """
        @param s: input string
        @return: the longest palindromic substring
        """
        def longestPalindrome(self, s):
            # write your code here
            start = end = 0
            n = len(s)
            dp = [[False]*n for _ in range(n)]
            for i in range(n-1, -1, -1): # for i in range(0, n) WRONG!!!!
                for j in range(i, n):
                    if i == j: 
                        dp[i][j] = True
                    else:
                        dp[i][j] = (s[i] == s[j]) and (j==i+1 or dp[i+1][j-1])
                    if dp[i][j] and (j-i+1) > (end-start):
                        start, end = i, j+1
            return s[start:end]
    

    Why is it not working if outside loop use for (int i = 0; i < n; i++)?

    因为推导公式里 i 依赖于 i+1,所以i+1要比 i 先算出来,所以要倒过来循环。

  • 相关阅读:
    Linux中history执行历史命令方法
    Linux中返回上一次目录
    Linux的vi编辑模式下常用快捷键
    [Android] TextView上同时显示图标和文字
    [Android] macOS的Android Studio快捷键
    [Android] 转-RxJava+MVP+Retrofit+Dagger2+Okhttp大杂烩
    [iOS] 测试设备解决自签名证书问题
    [macOS] keychain的跳坑之旅!git拉取的权限问题
    [PHP] swoole在daemonize模式下,chdir失效问题
    [macOS] macOS下,VirtualBox安装CentOS7.4, 搭建nginx, mysql, PHP5.6&PHP7.1
  • 原文地址:https://www.cnblogs.com/bonelee/p/10258863.html
Copyright © 2011-2022 走看看