剑指offer48 最长不含重复字符的子字符串

看到最长,先想DP。

暴力解法找到所有子字符串O(n^2)再O(n)判断是否重复,O(n^3)。从n中选一个开头,再从n中选一个结束,再去掉一般不是字符串的(开头大于结束)。

牛客网上又没有。这个值得写一下:

public class niuke48 {
    public String longestSubStringWithoutRepeat(String s) {
        if(s==null||s.length()<1) return "";
        
        int[] dp = new int[s.length()];
        int[] pos = new int[26];
        for(int i=0;i<pos.length;i++) pos[i]=-1;
        dp[0]=1;pos[s.charAt(0)-'a']=0;
        int max = dp[0];int maxIndex=0;
        //dp[i] 表示以charAt(i)结尾的子字符串最长无重复长度
        for(int i=1;i<s.length();i++) {
            char c = s.charAt(i);
            if(pos[c-'a']==-1) dp[i]=dp[i-1]+1;
            else {
                if(i-pos[c-'a']<=dp[i-1]) dp[i]=i-pos[c-'a'];
                else dp[i]=dp[i-1]+1;
            }
            if(dp[i]>max) {max=dp[i];maxIndex=i;}
        }
        return s.substring(maxIndex-max, maxIndex+1);
        
    }
}

 用pos记录字符上次出现的位置的思路挺好的。

class Solution(object):
    def getSubstring(self, astr):
        if astr is None or len(astr)<0:
            return ""
        dp = [0 for i in range(len(astr))]
        pos = [-1 for i in range(26)]
        dp[0] = 1
        pos[ord(astr[0])-ord('a')] = 0
        for i in range(1,len(astr)):
            asc2 = ord(astr[i])-ord('a')
            if pos[asc2]==-1:
                pos[asc2] = i
                dp[i] = dp[i-1]+1
            elif pos[asc2]<i-dp[i-1]:
                pos[asc2] = i
                dp[i] = dp[i - 1] + 1
            else:
                dp[i] = i-pos[asc2]
                pos[asc2] = i
        return max(dp)

if __name__=='__main__':
    sol = Solution()
    print sol.getSubstring("arabcacfr")

 

posted @ 2019-02-28 17:37  大胖子球花  阅读(178)  评论(0)    收藏  举报