您的位置:首页 > 其它

个人记录-LeetCode 3.Longest Substring Without Repeating Characters

2016-08-14 21:07 477 查看
问题:

Given a string, find the length of 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.

代码示例:

1、失败的O(N2)算法,可行但运行超时

public class Solution {
public int lengthOfLongestSubstring(String s) {
int max = 0;

if (s != null) {
int length = s.length();
//i表示不重复字符串的起始位置
//当i位置后的字符串数量小于当前的max时,就没有继续搜索的必要了
for (int i = 0; i < length - max; ++i) {
int curMax = searchFromCurIndex(i, s, length);
max = curMax > max ? curMax : max;
}
}

return max;
}

int searchFromCurIndex(int index, String str, int length) {
int next;
//next用来表示新加入的字符
for (next = index + 1; next < length; ++next) {
//新加的字符与已有的不重复,则继续增加下一个
if (str.substring(index, next).contains(String.valueOf(str.charAt(next)))) {
break;
}
}

return next - index;
}
}


这里存在的问题是:当检测到重复的字符时,下一次搜索应该越过重复的位置。

举例来说:

abcdef是个不重复的子串,abcdefc中前后两个c重复了。

那么下一次搜寻,应该跨过出现重复的地方进行,否则找出来的候选串依然有重复字符,且长度还不如上次的搜索。

所以下一次搜索,直接从第一个c的下一个字符d开始进行。

从宏观来讲,O(N2)算法的失败之处是:没有充分利用前一次搜索获得的有效信息。

2、改进的O(N)算法

public class Solution {
public int lengthOfLongestSubstring(String s) {
int max = 0;

if (s != null && s.length()> 0) {
max = 1;

int len = s.length();

int fstIndex = 0;
int secIndex = 1;

//positon就像一个hash表,每个字符对应的ascii码就是下标
//完全可以改为hashMap实现
int[] position = new int[65536];
for (int i = 0; i< 65536; ++i) {
position[i] = -1;
}
//存储的值为对应字符的在字符串中的位置
position[s.charAt(fstIndex)] = fstIndex;

//endMode表示是while循环结束后,是否需要重新计算max
boolean endMode = false;
while(secIndex < len) {
//表示新的字符还未重复
if (position[s.charAt(secIndex)] == -1) {
endMode = true;
} else {
//新的字符重复了
endMode = false;

//计算当前最大窗口
max = getMax(max, fstIndex, secIndex);

int oldFst = fstIndex;
//下一次的起点,修改为当前重复串字符,在string串位置的下一个
fstIndex = position[s.charAt(secIndex)] + 1;

//剩余的字符不足以改变最大长度了
if (fstIndex > len - max) {
break;
}

//由于起始位置改变了,对移除旧有的记录信息
for (int i = oldFst; i< fstIndex; ++i) {
position[s.charAt(i)] = -1;
}
}

//记录新字符的信息
position[s.charAt(secIndex)] = secIndex;
++secIndex;
}

//endMode为true,表示最后是以:secIndex == len为条件结束的
//即最后一次的while循环,没有发现重复字符
if (endMode) {
max = getMax(max, fstIndex, secIndex);
}
}

return max;
}

int getMax(int max, int fst, int sec) {
int curLen = sec - fst;
return max > curLen ? max : curLen;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: