Longest Substring Without Repeating Characters - 哈希与双指针
题意很简单,就是寻找一个字符串中连续的最长包含不同字母的子串。
其实用最朴素的方法,从当前字符开始寻找,找到以当前字符开头的最长子串。这个方法猛一看是个n方的算法,但是要注意到由于字符数目的限制,其实这是个O(Cn)的算法,最长也不过是C长度。所以我觉得普通方法应该是能过的。
于是写了一个,字符数目最大也不超过256所以代码如下:
1 class Solution { 2 public: 3 int lengthOfLongestSubstring(string s) { 4 5 int res=0; 6 for(int i=0;i<s.length();i++) 7 { 8 int flag[200]; 9 memset(flag,0,sizeof(flag)); 10 int count = 0; 11 flag[s[i]-' '] = 1; 12 int tempres = 1; 13 for (int j = i + 1; j < s.length(); j++) { 14 if (flag[s[j]-' ']==0) { 15 flag[s[j]-' ']= 1; 16 tempres++; 17 } else 18 break; 19 } 20 if (tempres > res) 21 res=tempres; 22 } 23 return res; 24 } 25 };
其中空格是ASCII码第一个实际意义字符,所以减去‘ ’
正常的O(n)方法是使用哈希表来存已经出现的字符,使用一个指针依次检索,如果碰到已经存在的字符,则去使用第二个指针更新这个哈希表。
从原理上来具体讨论双指针这个算法,对于第一个指针指到的字母有两种情况:
1.从来没有使用过
当前长度加一,将这个位置和字母加入哈希表,第二个指针不动
2.已经使用过,并且有一个哈希表存这个字母的上一个位置
获取上一个位置右侧位置(+1操作),将这个位置和第二个指针比较,
(1)如果小于第二个指针,说明以当前结尾的字符串在第j个指针的地方有字母重复,忽略这个位置,继续以j为准
(2)如果大于第二个指针,说明以当前结尾的字符串在这个最新的位置有重复,将指针移到这个位置,计算这个长度。
这三种情况涵盖了所有可能,并在下面的例子中有相应出现。
代码:
此代码来自最多discuss区最多vote的答案:https://leetcode.com/discuss/23883/11-line-simple-java-solution-o-n-with-explanation
1 public int lengthOfLongestSubstring(String s) { 2 if (s.length()==0) return 0; 3 HashMap<Character, Integer> map = new HashMap<Character, Integer>(); 4 int max=0; 5 for (int i=0, j=0; i<s.length(); ++i){ 6 if (map.containsKey(s.charAt(i))){ 7 j = Math.max(j,map.get(s.charAt(i))+1); 8 } 9 map.put(s.charAt(i),i); 10 max = Math.max(max,i-j+1); 11 } 12 return max; 13 }
例子:
对于这个字符串:abcbcda
经过初始化循环执行过程如下:
i=0; j=0; (a,0) max(0,1)=1 第一种情况
i=1; j=0; (b,1) max(1,2)=2 同上
i=2; j=0; (c,2) max(2,3)=3 同上
i=3; j=(0,1+1)=2; (b,3) max(3,2)=3 第二种第二个情况
i=4; j=(2,2+1)=3; (c,4) max(3,2)=3 同上
i=5; j=3; (d,5) max(3,3)=3 第一种情况
i=6; j=(3,1)=3; (a,6) max(3,4)=4 第二种第一个情况
posted on 2015-06-28 23:25 holyprince 阅读(259) 评论(0) 编辑 收藏 举报