标签:
刷leetcode,看到一个算法,给大神跪了。。。。看了半天才明白,下面谈谈理解
int lengthOfLongestSubstring(string s) { int locs[256];//存储已出现字符的上一次出现位置 int max = 0;//长度 int currenthead = -1;//初始计算长度的头部 memset(locs, -1, sizeof(locs)); for (int i = 0; i < s.size(); i++)//有点难想到,下面系统解释 { if (locs[s[i]] > currenthead) { currenthead = locs[s[i]]; } if (i - currenthead > max) { max = i - currenthead; } locs[s[i]] = i; } return max; }
这道题最朴素的想法,就是两层遍历:
1、第一层遍历所有字符,表示以每一位置的字符打头的子串;
2、第二层,以某一位置字符开头,向后遍历,可以用map容器插入操作判断是否有重复字符,并计算长度;
3、这样做的话,实际上是求出了字符串的所有无重复字符的子串,得到最大的长度,时间复杂度为O(N2)。
但是可以看到,第二层遍历与第一层是有重合的,因而是可以结合到第一层遍历的,方法就是利用一个额外的数组存放字符位置信息,具体思路如下:
1、两层遍历时,第二层遍历到了当前打头字符子串的一个重复字符时,第二层遍历停止,第一层遍历可以直接跳到该重复字符第一次出现的位置开始循环,因为头字符和该重复字符之间的字符作为头字符的子串不可能跳过该重复字符且长度必定低于当前头字符子串。
2、只用一层遍历,不停地更新存储字符出现的上一个位置,这样就相当于跳转了。
举个栗子,abccabc:
两层遍历时,会出现abc,bc,c,cab,abc等情况;采用上面算法,只会计算abc,cab,abc子串(粗略的表达一下不同,具体的位置下标值需慎重处理)。
这个算法是在对循环和字符子串问题特性的深刻理解基础上形成的,可以扩展到很多类似的有有重合部分的两层循环的问题;再一个,想要时间复杂度降低,必须得增大空间复杂度。
Longest Substring without Repeating Characters
标签:
原文地址:http://www.cnblogs.com/gaofeijin/p/5396909.html