您的位置:首页 > 其它

最长不含重复字符的字符串

2019-05-10 18:05 162 查看
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_41672180/article/details/90081581

题目

  • 请从字符串中找出一个最长的不包含重复字符的字符串,计算最长子字符串的长度;假设字符串中只包含‘a’~‘z’的字符;
  • 例如,在字符串“arabcacfr”中,最长的不包含重复子字符串是“acfr”,长度为4;

 

 

分析

  • 用动态规划来提高效率;首先定义一个函数f(i)表示以第i个字符为结尾的不包含重复字符的子字符串的最长长度;f(i-1)表示以第i-1个字符为结尾的不包含重复的字符串长度;
  • 如果第i个字符没有出现过,那么f(i)=f(i-1)+1;
  • 例如,在字符串“arabcacfr”中,显然f(0)等于1,;在计算f(1)时,下标为1的字符‘r‘之前也没有出现过,因此f(1)=2,即f(1) = f(0)+1;,到此为止,最长字符串为“ar”
  • 如果第i个字符之前已经出现过,那情况就复杂了;我们先计算第i个字符和他上次出现在字符串中的位置的距离,d;
  • 第一种情况:d<=f(i-1) ,此时第i个字符上次出现在f(i-1)对应的最长子字符串中,因此f(i)=d;我们接着上面的算f(2),下标为2的值是a,a之前出现过,上一次出现的位置是0,他们之间的距离是d=(i-preIndex)为2,也就是字符’a‘出现在f(1)对应的最长不含重复字符的子字符串“ar”中,此时f(2)=d,即f(2)=2;
  • 第二种情况:d>f(i-1),此时字符串上次出现的位置在f(i-1)对应的最长子字符串的前面,因此仍然有f(i)=f(i-1)+1;现在看最后一个字符’r‘就是,他重复的就不再前一个的最长子字符串里,所以还是f(8)=f(7)+1=4;

 

分析

  • 核心方法findLongestSubstring() curLen=0当前没有重复的字符串长度,也就是f(i-1)
  • maxLen=0最大字符串长度
  • 定义一个位置数组,表示当前的a~z在str里出现的位置
  • 最开始全都设成-1,证明没有在str里出现过
  • 从头开始遍历字符串 得到字符
  • char t=str.charAt(i);
  • 去位置数组里,找到该字符在str字符串里出现的位置,为-1就是没有出现过
  • int preIndex=position[t-'a']
  • 得到两个重复字符的距离(i-preIndex)用当前位置i,减去之前出现的位子
  • 如果preIndex=-1||d》curLen
  • preIndex等于-1就是代表没在str字符串里出现过,d》curLen出现的重复的字符不在f(i-1)里,所以没关系 当前长度++
  • 否则就是重复在当前长度里
      前面的就不要了,保留从现在开始
    • 当前长度=d
  • 记录一下当前字符出现在str里,position[str.charAt(i)-'a']=i
  • 如果当前长度》最大长度
      就赋值
  • 最后返回最大长度
  •  

     

     

     

     

     

     

     

     

     

    package No15_优化空间和时间效率;

     

    /**

     * 创建人:Jason

     * 创建时间:2019/1/18

     * 描述你的类:

     * //题目:请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子

     * //字符串的长度。假设字符串中只包含从'a'到'z'的字符。

     动态规划,

     定义f(i)表示以第i个字符为结尾的不含重复字符的子字符串长度。

     定义f(i -1)表示以第i-1个字符为结尾的不含重复字符的子字符串长度。

     如果第i个字符之前没有出现过,则f(i) = f(i -1) +1,比如‘abc',f(0) = 1是必然的,

     再字符'b'之前没有出现过, 则f(1) = f(0)+1,

     字符’c'之前没有出现过,那么f(2) = f(1) +1,每次计算都会用到上一次计算的结果。

     如果第i个字符之前出现过呢?找到该字符上次出现的位置preIndex,当前位置d=i-preIndex就得到这两个重复字符之间的距离, 设为d。

     此时有两种情况:

     如果d <= f(i-1),说明当前重复字符必然在f(i-1)所对应的字符串中,比如'bdcefgc',当前字符c前面出现过了,preIndex为2,

     此时d = 6 -2 = 4 ,小于 f(i -1) = 6 (bdcefg)我们只好丢弃前一次出现的字符c及其前面的所有字符,得到当前最长不含重复字符的子

     字符串为’efgc‘,即f(i) = 4, 多举几个例子就知道,应该让f(i) = d;

     如果d > f(i-1), 这说明当前重复字符必然出现在f(i-1)所对应的字符串之前,比如erabcdabr当前字符r和索引1处的r重复,

     preIndex =1, i = 8,d=(i-preIndex) = 7。而f(i -1) = 4 (取索引4之后不包含重复字符的串cdab),而7>4,

     此时直接加1即可, 即f(i) = f(i-1) +1

     */

    public class LongestSubstringWithoutDup {

     

    //核心方法

    public int findLongestSubstring(String str){

     

    //当前长度

    int curLen = 0;

    //最大长度

    int maxLen = 0;

     

    //定义一个位置数组,用来储存该字符出现在str的位置

    int []pos = new int[26];

    for(int i = 0;i < 26;i++){

    //初始化全是-1

    pos[i] = -1;

    }

     

     

    //从头开始遍历字符串

    for(int i = 0;i < str.length();i++){

    char t = str.charAt(i);

    //查看该字符是否出现在str里,如果出现过的话,preIndex就不是-1

    int preIndex = pos[t-'a'];

     

    //得到两个重复字符的距离,查看这个距离和f(i-1)的大小,这个重复的是数,是否在f(i-1)里

    int d = i - preIndex;

    //不重复或者重复在外面,不在f(i-1)里面

    if(preIndex == -1 || d > curLen){

    curLen++;

    }

    //如果在里面的话,前面就不要了,从该位置开始

    else{

    curLen = d;

    }

    //证明该点出现过

    pos[t-'a'] = i;

    if(curLen > maxLen){

    maxLen = curLen;

    }

    }

     

    return maxLen;

    }

     

     

    7ff7

        // ====================测试代码====================

        void testSolution1(String  input, int expected){

            int output = findLongestSubstring(input);

            if(output == expected)

                System.out.printf( "passed, with input: "+input+" expected:"+expected+"\n");

            else

                System.out.printf( "FAILED, with input: " +input+"\n");

        }

     

     

     

        void test(String  input, int expected){

            testSolution1(input, expected);

        }

     

        void test1(){

            String  input = "arabcacfr";

            int expected = 4;

            test(input, expected);

        }

     

        void test2()

        {

            String  input = "acfrarabc";

            int expected = 4;

            test(input, expected);

        }

     

        void test3()

        {

            String  input = "arabcacfr";

            int expected = 4;

            test(input, expected);

        }

     

        void test4()

        {

            String  input = "aaaa";

            int expected = 1;

            test(input, expected);

        }

     

        void test5()

        {

            String  input = "abcdefg";

            int expected = 7;

            test(input, expected);

        }

     

        void test6()

        {

            String  input = "aaabbbccc";

            int expected = 2;

            test(input, expected);

        }

     

        void test7()

        {

            String  input= "abcdcba";

            int expected = 4;

            test(input, expected);

        }

     

        void test8()

        {

            String  input = "abcdaef";

            int expected = 6;

            test(input, expected);

        }

     

        void test9()

        {

            String  input= "a";

            int expected = 1;

            test(input, expected);

        }

     

        void test10()

        {

            String  input = "";

            int expected = 0;

            test(input, expected);

        }

     

        public static void  main(String args[]){

            new LongestSubstringWithoutDup().test1();

            new LongestSubstringWithoutDup().test2();

            new LongestSubstringWithoutDup().test3();

            new LongestSubstringWithoutDup().test4();

            new LongestSubstringWithoutDup().test5();

            new LongestSubstringWithoutDup().test6();

            new LongestSubstringWithoutDup().test7();

            new LongestSubstringWithoutDup().test8();

            new LongestSubstringWithoutDup().test9();

            new LongestSubstringWithoutDup().test10();

        }

     

     

    }

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: