Given a string,find the length of the longest substring without repeating characters. Forexample, 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.
解法:
使用一个256的int数组indexs来记录每个char在字符串中出现的位置;
如果indexs[i]为-1,表示当前测试字符串中没有出现过字节i,因此直接将indexs[i]赋值为i,即记录其出现位置;
如果indexs[i]不为-1,则表示已经出现过,这里要根据此算法分成两种情况讨论;这里使用一个start记录当前测试字符串的起始位置,即当前测试的字符串为start--i;如果indexs[i]小于start,表示该字节出现在测试字符串之前,因此可以当做-1情况对待;再者,如果已经存在,则当前字符串已经不是满足要求的唯一性字符串了,因此计算当前的非重复最大值,和系统当前记录的最大值作比较,记录更大值;然后测试下一个字符串,为满足非重复条件,则下一个测试字符串的起始位置需要从index[start]+1开始;
public class Solution {
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0)
return 0;
char[] datas = s.toCharArray();
// 记录每个字节出现的位置
int[] indexs = new int[256];
// 进行初始化
Arrays.fill(indexs, -1);
// 记录最大长度
int max = 0;
// 记录每次测试的最长字符串的起始位置
int start = 0;
// 遍历
for (int i = 0; i < datas.length; i++) {
char data = datas[i];
// 如果当前字符不存在
if (indexs[data] == -1) {
indexs[data] = i;
} else {
int cur_index = indexs[data];
// 注意,如果当前存储的该字符位置再start之前,表示不在当期测试字符串中,因此可以当做-1来对待
if (cur_index >= start) {
// 更新最大值;以及下一个测试字符串的起始位置
max = Math.max(max, i - start);
start = cur_index + 1;
}
indexs[data] = i;
}
}
// 注意不要忽略最后一个测试字符串
return Math.max(s.length() - start, max);
}
}
运行结果:
解法一:
分析:1.使用一个标志数组boolean flag[256],标识每个字符是否出现过(注意考虑字符不要仅限于’a,b,c’) (上面例子则使用ArrayList或者HashMap来实现同样的记录功能,明显性能较差)。
2.acetbglsbcd:这里算法对其进行遍历,遇到重复的字符,记录下当前最大的字符长度;下一循环从该重复字符的第一位置加1(k+1)开始即可
public static int lengthOfLongestSubstring3(String s) {
//注意判断String要注意同时判断是否为null及空字符串
if((s == null)||(s.equals("")))
{
return 0;
}
//用以记录256个字符都是否出现没
boolean[] flag = new boolean[256];
int maxLength = 0;
int startindex = 0;
char[] chars = s.toCharArray();
for(int i = 0; i < chars.length; i++)
{
//判断字符是否已经出现,与HashMap一样都是O(1)
if(flag[chars[i]])
{
//记录最长字符串的长度
maxLength = Math.max(maxLength, i - startindex);
//更新标志数组的值
//注意这里每次遍历的字符串都会更新,故应该从startindex开始
for(int j = startindex; j < i; j++)
{
if(chars[i] == chars[j])
{
startindex = j + 1;
break;
}
//清除在重服字符出现的字符标志
flag[chars[j]] = false;
}
}
//未出现情况:注意这个重服出现的字符也要置为真
flag[chars[i]] = true;
}
//考虑一次遍历完全,而没有重服字符的情况
return Math.max(maxLength, chars.length - startindex);
}
解法二:
时间复杂度较差的解法:
使用ArrayList或者HashMap集合实现:
public static int lengthOfLongestSubstring(String s) {
//注意判断String要注意同时判断是否为null及空字符串
if((s == null)||(s.equals("")))
{
return 0;
}
int maxLength = 0;
int tempLength = 0;
char[] chars = s.toCharArray();
List<Character> arrayList = new ArrayList<>();
for(int i = 0; i < chars.length; i++)
{
if(!arrayList.contains(chars[i]))
{
arrayList.add(chars[i]);
tempLength ++;
}
else
{
arrayList.add(chars[i]);
maxLength = (maxLength > tempLength) ? maxLength : tempLength;
int index = arrayList.indexOf(chars[i]);
arrayList = arrayList.subList(index, arrayList.size()-1);
/*使用一步一步清除一定要注意每一步remove都是独立的*/
// for(int j = 0 ;j <= index; j++)
// {
// arrayList.remove(0);//注意这一步
// }
tempLength = arrayList.size();
}
}
//考虑整条字符串都无重复的情况
maxLength = (maxLength > tempLength) ? maxLength : tempLength;
return maxLength;
}
</pre><pre class="java" name="code">public static int lengthOfLongestSubstring2(String s) {
//注意判断String要注意同时判断是否为null及空字符串
if((s == null)||(s.equals("")))
{
return 0;
}
int maxLength = 0;
int startindex = 0;
int tempLength = 0;
char[] chars = s.toCharArray();
HashMap<Character, Integer> map = new HashMap<>();
for(int i = 0; i < chars.length; i++)
{
if(map.containsKey(chars[i]))
{
maxLength = (maxLength > tempLength) ? maxLength : tempLength;
int index = map.get(chars[i]);
for(int j = startindex; j <= index; j++)
{
map.remove(chars[j]);
}
startindex = index;
}
map.put(chars[i], i - startindex);
tempLength = map.size();
}
//考虑整条字符串都无重复的情况
maxLength = (maxLength > tempLength) ? maxLength : tempLength;
return maxLength;
}