Fork me on GitHub

【Offer】[48] 【最长不含重复字符的子字符串】

题目描述

  请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。假设字符串中只包含'a'~'z'的字符。例如,在字符串"arabcacfr"中,最长的不含重复字符的子字符串是"acfr",长度为4。

牛客网刷题地址

思路分析

  动态规划算法。首先定义函数f(i)表示以第i个字符为结尾的不包含重复字符的子字符串的最长长度。我们从左到右逐扫描字符串中的每个字符。当我们计算以第i个字符为结尾的不包含重复字符的子字符串的最长长度f(i)时, 我们已经知道f(i-1)了,分为下面的几种情况:

  1. 如果第i个字符之前没有出现过,那么 f(i) = f(i-1)+1;
  2. 如果出现过,计算第i个字符与它上次出现的位置之间的距离d,这个可以利用一个数组缓存起来,之后分为两种情况:
    1. 如果d小于或者等于f(i-1),f(i)=d;
    2. 如果d大于f(i-1),f(i) = f(i-1)+1;

测试用例

  1. 功能测试:包含多个字符的字符串;只有一个字符的字符串;所有字符都唯一的字符串; 所有字符都相同的字符串。
  2. 特殊输入测试:空字符串。

Java代码

public class Offer048 {
    public static void main(String[] args) {
        test1();
        test2();
        test3();
        
    }

    public static int LongSubStringWithOutDup(String str) {
        return Solution1(str);
    }
    private static int Solution1(String str) {
        if(str==null || str.length()<=0) {
            return 0;
        }
        int preLength = 0;
        int curLength = 0;
        int maxLength = 0;
        int[] position = new int[26];
        for(int i=0;i<position.length;i++) {
            position[i]=-1;
        }
        for(int i=0;i<str.length();i++) {
            int prevIndex = position[str.charAt(i)-'a'];
            if( prevIndex <0 || i-prevIndex > preLength) {
                // 第i个字符之前没有出现过或者出现过但是距离大于f(i-1)
                curLength = preLength+1;
            }else {
                curLength = i-prevIndex;
            }
            position[str.charAt(i)-'a'] = i;
            if(curLength>maxLength) {
                maxLength=curLength;
            }
            preLength = curLength;
        }
        
        return maxLength;
    }

    private static void test1() {
        int result = LongSubStringWithOutDup("arabcacfr");
        System.out.println(result);
    }

    private static void test2() {

    }
    private static void test3() {

    }

}

代码链接

剑指Offer代码-Java

posted @ 2019-08-20 16:07  这个世界~  阅读(145)  评论(0)    收藏  举报