《剑指offer—面试题48:最长不含重复字符的子字符串》
注明:仅个人学习笔记
方法一参考:https://blog.csdn.net/qq_28618765/article/details/65627503
方法二参考:https://blog.csdn.net/m0_37862405/article/details/80369128
import java.util.HashMap;
import java.util.Map;
/**
*
*
* 最长不含重复字符的子字符串 如在字符串”arabcacfr”,其中最长不含重复字符的子字符串是“acfr”
*
*/
public class LongestSubstringWithoutDuplication48
{
public int lengthOfLongestSubstring(String s)
{
// 字符串输入不合法
if (s == null)
{
return 0;
}
// 当前处理的开始位置
int start = 0;
// 记录到的最大非重复子串长度
int result = 0;
// 访问标记,记录最新一次访问的字符和位置
Map<Character, Integer> map = new HashMap<>(s.length());
for (int i = 0; i < s.length(); i++)
{
char ch = s.charAt(i);//得到当前遍历的字符
// 如果遍历的当前字符之前出现过,且上一次出现的位置大于等于子串起始位置,也就是说该字符上一次出现时在子串中
// 如果字符已经出现过(在标记开位置算起),就重新标记start
if (map.containsKey(ch) && map.get(ch) >= start)
{
start = map.get(ch) + 1;// 此时,子串的起始位置更新为,从当前字符上一次出现时的下一个字符开始
}
// 如果没有出现过就求最大的非重复子串的长度
else
{
// 如果当前没出现过或者说是没有出现在以start开始的子串中,那就意味着直接加上当前字符,更新子串长
//更新最大非重复子字符串的长度
result = Math.max(result, i - start + 1);
}
// 更新访问记录
map.put(ch, i);// 更新当前字符出现的位置
}
return result;
}
private static int findLongestSubstringLength(String string)
{
if (string == null || string.equals(""))
return 0;
int maxLength = 0;
int curLength = 0;
// positions 用来保存每个字符上次出现在字符串中位置的下标
int[] positions = new int[26];// 用于记录当前字符上一次出现的位置
for (int i = 0; i < positions.length; i++)
{
positions[i] = -1; // 初始化为-1,负数表示没出现过
}
for (int i = 0; i < string.length(); i++)
{
// 判断遍历时,当前字符的合法性
if (!(string.charAt(i) >= 'a' && string.charAt(i) <= 'z'))
{
System.err.println("error!! ---Invalid input!!");
return 0;
}
// 这里做一个转换,一是同样可以表示当前字符,二是同时作为保存字符出现位置的数组的索引;
// 索引即使代表的某一字符,其数组值代表出现的位置;和用hashmap一样,那个里面是key代表字符,value代表字符出现的位置
int curChar = string.charAt(i) - 'a';// 当前字符是哪一个
int prePosition = positions[curChar];// 当前一字符上一次出现的位置
// 当前字符与它上次出现位置之间的距离
int distance = i - prePosition;
// 当前字符第一次出现,或者前一个非重复子字符串中没有包含当前字符
if (prePosition < 0 || distance > curLength)
{
curLength++;
} else
{
// 更新最长非重复子字符串的长度//这部分不去更新maxLength也可以
if (curLength > maxLength)
{
maxLength = curLength;
}
curLength = distance;
}
positions[curChar] = i; // 更新字符出现的位置
}
if (curLength > maxLength)
{
maxLength = curLength;
}
return maxLength;
}
public static void main(String[] args)
{
int i = findLongestSubstringLength("arab");
System.out.println(i);
}
}