Leetcode #3 Longest Substring Without Repeating Characters
来源:互联网 发布:c语言强制类型转换规则 编辑:程序博客网 时间:2024/06/05 20:15
Source: https://leetcode.com/problems/longest-substring-without-repeating-characters/
3. Longest Substring Without RepeatingCharacters
Given a string, find the lengthof the longest substring without repeating characters.
Examples:
Given "abcabcbb"
, the answer is "abc"
,which the length is 3.
Given "bbbbb"
, the answer is "b"
,with the length of 1.
Given "pwwkew"
, the answer is "wke"
,with the length of 3. Note that the answer must be a substring, "pwke"
is a subsequence and not a substring.
Solution:
我试着用两种方法解决这个问题:
方法一:
申请一个count数组,长度即原字符串s的长度length。count[i]记录着以第i个字符为首字符的无重复元素最长子字符串的长度。count[i]的计算用到了三层循环:
第一层:用i作检索,i的范围从0到length-1。初始化count[i]为1,置bool类型变量rpt为0;
第二层:用j检索原字符串中,第i个字符之后的字符。在第三层循环结束后,如果rpt变为1,则跳出该层循环;否则count[i]++;
第三层:用k检索s[i]到s[j-1]中的字符,将其与s[j]比较。如果相等,置rpt为1,跳出该层循环。
这个方法的时间复杂度为O(n3),这里n即为length。代码如下:
class Solution {public: int lengthOfLongestSubstring(string s) { int i,j,k; int ans=0; bool rpt; i=0; while (s[i]!='\0') i++; const int length=i; int count[length]; for (i=0;i<length;i++) { count[i]=1; rpt=0; for (j=i+1;j<length;j++) { for (k=i;k<=j-1;k++) { if (s[j]==s[k]) { rpt=1; break; } } if (rpt==1) break; else { count[i]++; } } if (count[i]>ans) ans=count[i]; } return ans; }};
方法二:
方法一在数据规模较大时,会有超时问题,因此在这里考虑时间复杂度更低的做法。假设s[i] s[i+1] s[i+2] … s[j-1]为最长的以s[i]为首的无重复元素的字符串,那么这意味着s[j]必然与这一字符串中某个字符相同。这里引入firstRpt数组,长度为length,firstRpt[i]=j。那么,这一无重复字符的字符串长度为firstRpt[i]-i。只要得到该数组,经过一次循环便能得到最长的无重复字符的字符串的长度。这一部分时间复杂度为O(n)。
为了得到firstRpt数组,另外引入一个长度相同的数组nextRpt,若nextRpt[i]=j,则s[j]为s[i]在原字符串之后第一个和s[i]相同的字符。从nextRpt数组得到firstRpt数组的方法为,从原字符串的末尾开始向前遍历,如果nextRpt[i]<firstRpt[i+1],意味着s[i]与s[i+1] s[i+2] s[i+3] … s[firstRpt[i+1]-1]中的某一个相同,则firstRpt[i]=nextRpt[i];否则,firstRpt[i]=firstRpt[i+1]。显然,初始条件为firstRpt[length-1]=length。这一部分时间复杂度为O(n)。
可以使用两层循环得到nextRpt数组:
第一层:用i作检索,i的范围从0到length-1。
第二层:用j作检索,j的范围从i+1到length-1。只要s[j]=s[i],则置next[i]=j,并跳出该层循环。
这一部分时间复杂度为O(n2),因而总的时间复杂度为O(n2)。这种做法代码如下:
class Solution {public: int lengthOfLongestSubstring(string s) { int i=0,j; int ans=0; while (s[i]!='\0') i++; const int length=i; int nextRpt[length]; int firstRpt[length]; for (i=0;i<length;i++) { nextRpt[i]=length; for (j=i+1;j<length;j++) { if (s[j]==s[i]) { nextRpt[i]=j; break; } } } firstRpt[length-1]=length; for(i=length-2; i>=0; i--) { if (nextRpt[i] < firstRpt[i+1]) firstRpt[i] = nextRpt[i]; else firstRpt[i] = firstRpt[i+1]; } if (length>0) ans=firstRpt[0]-0; for (i=1;i<length;i++) { j=firstRpt[i]-i; if (j>ans) ans=j; } return ans; }};
改进后的方法二:
方法二是可以通过所有测试样例的,但是这里仍然考虑更优的做法。关键在于,能否更快地得到next数组,将时间复杂度降下来。由于字符串的字符是有限的,规模不算太大,因而可以牺牲一部分空间建得一个表latestIndex,大小为ASCII码表的大小(实际上常常用不到这么多),其存储每一个字符最近出现的位置,即其在字符串中出现的下标。对于未出现过的字符,将其位置置为length。那么,从原字符串最后开始向前遍历,先记nextRpt[i]=latestIndex[s[i]],再更新latestIndex[s[i]]=i,即可在O(n)的时间内,得到nextRpt数组。因此,改进后的方法二的时间复杂度为O(n),同时,由于申请了字符串长度大小的两个数组firstRpt与nextRpt,空间复杂度同为O(n)。这种做法代码如下:
class Solution {public: int lengthOfLongestSubstring(string s) { int i=0,j; int ans=0; while (s[i]!='\0') i++; const int length=i; int latestIndex[256]; for (i=0;i<256;i++) { latestIndex[i]=length; } int nextRpt[length]; int firstRpt[length]; for (i=length-1;i>=0;i--) { nextRpt[i]=latestIndex[s[i]]; latestIndex[s[i]]=i; } firstRpt[length-1]=length; for(i=length-2; i>=0; i--) { if (nextRpt[i] < firstRpt[i+1]) firstRpt[i] = nextRpt[i]; else firstRpt[i] = firstRpt[i+1]; } if (length>0) ans=firstRpt[0]-0; for (i=1;i<length;i++) { j=firstRpt[i]-i; if (j>ans) ans=j; } return ans; }};
- LeetCode 3 - Longest Substring Without Repeating Characters
- LeetCode 3: Longest Substring Without Repeating Characters
- leetcode-3:Longest Substring Without Repeating Characters
- LeetCode(3) Longest Substring Without Repeating Characters
- leetcode 3LONGEST SUBSTRING WITHOUT REPEATING CHARACTERS
- Leetcode【3】:Longest Substring Without Repeating Characters
- [leetcode 3] Longest Substring Without Repeating Characters
- [Leetcode] 3 - Longest Substring Without Repeating Characters
- LeetCode 3:《Longest Substring Without Repeating Characters》
- [leetcode 3] Longest Substring Without Repeating Characters
- [leetcode] 3 Longest Substring Without Repeating Characters
- [Leetcode]3Longest Substring Without Repeating Characters
- leetcode 3 Longest Substring Without Repeating Characters
- LeetCode #3 Longest Substring Without Repeating Characters
- leetcode-3 Longest Substring Without Repeating Characters
- LeetCode 3 Longest Substring Without Repeating Characters
- leetcode 3: Longest Substring Without Repeating Characters
- LeetCode 3 Longest Substring Without Repeating Characters
- 设计模式(16)-迭代器模式(Iterator)
- 猫猫学IOS(三十一)UI之Quartz2D图形上下文栈
- 丫头还是别做程序猿了。。。
- 猫猫学IOS(三十三)UI之Quartz2D雪花飘落效果刷帧
- 用Qt Creator编写一个简单的窗口程序
- Leetcode #3 Longest Substring Without Repeating Characters
- Unity3D中函数执行顺序
- 不会排序的司机不是好司机——八大排序算法
- 面向对象 重中之重
- HG - Hexo + GitHub + Travis CI = 自动部署博客实现
- linux 在 cpu/内存 使用率
- 各种姿势折腾 QEMU
- 学习shader之前必须知道的东西之计算机图形学——渲染管线
- JSP中的EL表达式和JSTL标签库