【JAVA、C++】LeetCode 003 Longest Substring Without Repeating Characters

时间:2021-01-20 15:12:34

Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest substring is "b", with the length of 1.

解题思路一

由于题目给个tag为HashTable和Two Pointers

因此,我们可以定义一个HashTable,和两个Pointers,index1和index2,首先将String中元素不断添加进去,如果发现重复,则删除重复的元素和它之前的元素,它们在String中的位置分别用index1和index2进行标记,最后找到HashTable曾经的最大规模。这种思路的时间复杂度为O(n)代码如下

public class Solution {
static public int lengthOfLongestSubstring(String s) {
char[] char1 = s.toCharArray();
int longestLength = 0;
int startIndex = 0;
int lastIndex = 0;
HashMap<Character, Integer> hashMap = new HashMap<Character, Integer>();
for (int i = 0; i < char1.length; i++) {
if (hashMap.containsKey(char1[i])) {
lastIndex = hashMap.get(char1[i]);
if (longestLength < (i - startIndex)) {
longestLength = i - startIndex;
}
for (int j = startIndex; j <= lastIndex; j++) {
hashMap.remove(char1[j]);
}
startIndex = lastIndex+1;
}
hashMap.put(char1[i], i);
}
if(longestLength<char1.length-startIndex)
longestLength=char1.length-startIndex;
return longestLength;
}
}

但是,提交之后显示Time Limit Exceeded,看来时间复杂度还是太高,究其原因,在于中间有两个for循环,第二个for循环每进行一次删除都必须遍历一边,因此时间开销必然很大。

思路二:

其实每次添加过后,我们不一定要在HashMap中删除重复的元素,我们可以用一个指针记录需要删除元素的位置,如果出现重复元素,就把pointer置为重复元素最后一次出现的位置+1即可,判断之前最大的substring的长度和本次产生的substring长度的大小。之后将本元素添加进HashMap里面。当然,最后还需要判断下最后一次获得的子串的长度和之前长度的比较。

Java代码如下:

public class Solution {
static public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> hashMap = new HashMap<Character, Integer>();
int length = 0;
int pointer = 0;
for (int i = 0; i < s.length(); i++) {
if (hashMap.containsKey(s.charAt(i))&& hashMap.get(s.charAt(i)) >= pointer) {
length = Math.max(i-pointer, length);
pointer = hashMap.get(s.charAt(i)) + 1;
}
hashMap.put(s.charAt(i), i);
}
return Math.max(s.length() - pointer, length);
}
}

C++代码如下:

 #include<vector>
#include<unordered_map>
#include<string>
#include<algorithm>
using namespace std;
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<char, int> map;
int res = ;
int pointer = ;
int size = s.length();
for (int i = ; i < size; i++) {
unordered_map < char, int >::iterator iter;
iter = map.find(s[i]);
if (iter != map.end() && map[s[i]] >= pointer) {
res = max(res, i - pointer);
pointer = map[s[i]] + ;
}
if (iter != map.end())
map[s[i]] = i;
else
map.insert(unordered_map<char, int>::value_type(s[i], i));
}
return max(size - pointer,res);
}
};

解题思路三:

由于字母有限,使用STL中map开销太大直接使用数组实现map映射即可,C++实现如下:

 #include<string>
#include<algorithm>
using namespace std;
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int res = , point = ;
int prev[];
memset(prev, -, sizeof(prev));
for (int i = ; i < s.length(); i++) {
if (prev[s[i]] >= point)
point = prev[s[i]] + ;
prev[s[i]] = i;
res = max(res, i - point + );
}
return res;
}
};