题目大意是传入一条字符串,计算出这样的这样一条子字符串,要求子字符串是原字符串的连续的某一段,且子字符串内不包含两个或两个以上的重复字符。求符合上面条件的字符串中最长的那一条的长度。


首先注意到任意一条无重复子字符串的任意子字符串应该也满足无重复这一特性。因此这个问题可以用动态规划解决。

需要先计算出字符串s的每个元素对应的首个重复字符的下标,字符串中下标为i的元素的首个重复字符的下标j应该满足j > i && s[i] == s[j],且是满足这些条件中的最小值。比如asaa中下标为0的元素对应的首个重复字符的下标为2,尽管3也满足条件,但不是最小值。

计算的方式如下:

registries = int[256]

nextOccurance = int[s.length]

initialize elements in registries with -1 //将所有registries 中的元素都初始化为-1

initialize elements in nextOccurance with s.length //将所有registries 中的元素都初始化为s.length

for(i = 0; i < s.length; i++)

  c = s[i]

  if registries[c] != -1 then

    nextOccurance [registries[c]] = i

  registries[c] = i

这里用注册表registries的注册项registries[c]记录当前对字符c的查找请求,而nextOccurance的元素nextOccurance[i]表示s[i]的首个重复字符子s中的下标。每次循环时,都会检测注册表项registries[c]是否以及被注册,如果注册则为nextOccurance [registries[c]]记录当前下标i。最后则将之前的注册项清除,而用当前下标作为新的请求项。

之后使用动态规划解决问题。利用数组longestLengthes,longestLengthes[i]表示所有以下标i作为起始的无重复子字符串的最长长度。显然longestLengthes[s.length - 1]应该为1。而对于任意i < s.length - 1,应该有longestLengthes[i] = min(longestLengthes[i + 1] + 1, nextOccurance [i] - i)。其中longestLengthes[i + 1] + 1表示理想状态下(不考虑出现多个longestLengthes[i]对应的字符)的最优长度,而nextOccurance [i] - i表示可能的以下标i作为起始的无重复子字符串的最长长度,因为s[i] == s[nextOccurance [i]],这里已经发生了重复。之所以敢保证longestLengthes[i] <= longestLengthes[i + 1] + 1是因为假如longestLengthes[i]>longestLengthes[i + 1] + 1,那么显然longestLengthes[i + 1] >= longestLengthes[i] - 1 >longestLengthes[i + 1](整体不重复自然局部不会重复),这是不可能发生的。(如果对这部分不理解,可以枚举可能的情况,总共只有三种)转换成代码:

longestLengthes = int[s.length]

longestLengthes[s.length - 1] = 1

for(i = s.length - 2; i >= 0; i--)

  longestLengthes[i] = min(longestLengthes[i + 1] + 1, nextOccurance [i] - i)

之后遍历整个longestLengthes数组就可以找到最长的无重复子字符串的长度。

把上面两部分的代码整合,可以轻易得出整体的复杂度为O(n),其中n为传入字符串的长度。


最后给出整个实现代码,给有需要的人:

package cn.dalt.leetcode;

/**
 * Created by Administrator on 2017/6/4.
 */
public class LongestSubstringWithoutRepeatingCharacters {
    public static void main(String[] args) {
        String s = "yiwgczzovxdrrgeebkqliobitcjgqxeqhbxkcyaxvdqplxtmhmarcbzwekewkknrnmdpmfohlfyweujlgjf";
        System.out.println(new LongestSubstringWithoutRepeatingCharacters().lengthOfLongestSubstring(s));
        for(char c = 0; c < 256; c++)
        {
            System.out.println((int)c + ":" + c);
        }
    }

    int[] nextOccurIndexes = null;
    int[] registries = new int[1 << 8];

    public int lengthOfLongestSubstring(String s) {
        //Calculate all next occur indexes
        //nextOccurIndexes[i] is the minimun index of s which has properties that index > i && s[i] = s[index]
        int slength = s.length();
        if (slength == 0) {
            return 0;
        }
        nextOccurIndexes = new int[s.length()];
        for (int i = 0, bound = registries.length; i < bound; i++) {
            registries[i] = -1;
        }
        for (int i = 0, bound = s.length(); i < bound; i++) {
            int c = s.charAt(i);
            int registry = registries[c];
            if (registry != -1) {
                nextOccurIndexes[registry] = i;
            }
            registries[c] = i;
        }
        for (int registry : registries) {
            if (registry != -1) {
                nextOccurIndexes[registry] = slength;
            }
        }

        int[] longestNoneRepetitionSubstringLengthes = new int[s.length()];
        longestNoneRepetitionSubstringLengthes[s.length() - 1] = 1;
        int longestNoneRepetitionSubstringIndex = s.length() - 1;
        for (int i = s.length() - 2; i >= 0; i--) {
            int probablyMaxLength1 = longestNoneRepetitionSubstringLengthes[i + 1] + 1;
            int probablyMaxLength2 = nextOccurIndexes[i] - i;
            longestNoneRepetitionSubstringLengthes[i] = Math.min(probablyMaxLength1, probablyMaxLength2);
            longestNoneRepetitionSubstringIndex =
                    longestNoneRepetitionSubstringLengthes[i] > longestNoneRepetitionSubstringLengthes[longestNoneRepetitionSubstringIndex] ?
                            i : longestNoneRepetitionSubstringIndex;
        }
        return longestNoneRepetitionSubstringLengthes[longestNoneRepetitionSubstringIndex];
    }
}

Leetcode:Longest Substring Without Repeating Characters分析和实现的更多相关文章

  1. [LeetCode] Longest Substring Without Repeating Characters 最长无重复子串

    Given a string, find the length of the longest substring without repeating characters. For example, ...

  2. leetcode: longest substring without repeating characters

    July 16, 2015 Problem statement: Longest Substring Without Repeating Characters Read the blog: http: ...

  3. LeetCode:Longest Substring Without Repeating Characters(最长不重复子串)

    题目链接 Given a string, find the length of the longest substring without repeating characters. For exam ...

  4. [LeetCode] Longest Substring Without Repeating Characters 最长无重复字符的子串

    Given a string, find the length of the longest substring without repeating characters. Example 1: In ...

  5. C++ leetcode Longest Substring Without Repeating Characters

    要开学了,不开森.键盘声音有点大,担心会吵到舍友.今年要当个可爱的技术宅呀~ 题目:Given a string, find the length of the longest substring w ...

  6. [LeetCode]Longest Substring Without Repeating Characters题解

    Longest Substring Without Repeating Characters: Given a string, find the length of the longest subst ...

  7. [LeetCode] Longest Substring Without Repeating Characters 最长无重复字符的子串 C++实现java实现

    最长无重复字符的子串 Given a string, find the length of the longest substring without repeating characters. Ex ...

  8. LeetCode——Longest Substring Without Repeating Characters

    Given a string, find the length of the longest substring without repeating characters. For example, ...

  9. [Leetcode] Longest Substring Without Repeating Characters (C++)

    题目: Given a string, find the length of the longest substring without repeating characters. For examp ...

随机推荐

  1. Mac安装并破解StarUML

    1.下载与安装这里不做赘述,直接去官网下载即可 http://staruml.io/ 2.关键的事情来了,破解 一.打开安装包的目录 cd /Applications/StarUML.app/Cont ...

  2. 程序员有什么办法能快速梳理java知识点?有这八张图就够了

    一图胜千言,下面图解均来自Program Creek 网站的Java教程,目前它们拥有最多的票选.如果图解没有阐明问题,那么你可以借助它的标题来一窥究竟. 1.字符串不变性 下面这张图展示了这段代码做 ...

  3. SQL面试题-行列互换-if、【case when】

    http://www.cda.cn/view/21469.html tb_lemon_grade中,表中字段id,student_name,course,score分别表示成绩id,学生姓名,课程名称 ...

  4. Bellman-Ford算法——解决负权边

    Dijkstra算法虽然好,但是它不能解决带有负权边(边的权值为负数)的图. 接下来学习一种无论在思想上还是在代码实现上都可以称为完美的最短路径算法:Bellman-Ford算法. Bellman-F ...

  5. 窗口玻璃特效,半透明窗口,使用DWM实现Aero Glass效果

    转自:http://blog.csdn.net/ntwilford/article/details/5656633 从Windows Vista开始,Aero Glass效果被应用在了Home Pre ...

  6. 如何移除双系统mac中的windows系统

    双系统 双系统即在电脑的不同分区中安装两个系统,两个系统不会互相影响,但是同时只能有一个系统正在运行,并且必须通过重启的方式来更换系统. 双系统一般由于解决对不同系统的需求,而且在电脑中直接安装系统也 ...

  7. CSS3的圆角border-radius属性

    一,语法解释 border-radius : none | <length>{1,4} [/ <length>{1,4} ] <length>: 由浮点数字和单位标 ...

  8. fn project 试用之后的几个问题

    今天试用fnproject  之后自己有些思考,后面继续解决   1. 目前测试是强依赖 dockerhub 的,实际可能不是很方便 2. 如何与k8s .mesos.docker swarm  集成 ...

  9. iOS侧滑返回到隐藏导航栏的VC,导航栏会闪现一次

    VCA:是一个隐藏导航栏的页面:VCA在ViewWillAppear生命周期函数中设置导航栏隐藏: //隐藏导航栏 [self.navigationController setNavigationBa ...

  10. maven依赖顺序原则

    使用maven的程序员都会遇到一个问题,那就是maven依赖冲突的问题,这会导致ClassNotFound或者MethodNotFound这样的异常.其实只要明白maven依赖的根本性的原则就不怕这样 ...