题目
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
临界情况
- aaaaaa 此时最长子字符串长度为1
- pwwkew 此时最长子字符串为kew,长度为3
题解
动态规划 1.0(数组版)
核心思路是找到每个字符对应的子字符串的大小,再取最大值
最优子结构性质
当 dp[i−1] < i−left ,说明字符 s[left] 在子字符串 dp[i−1] 区间之外 ,则 dp[i] = dp[i−1]+1 ;
当 dp[i−1] ≥ i−left ,说明字符 s[left] 在子字符串 dp[i−1] 区间之中 ,则 dp[i] 的左边界由 s[left] 决定,即 dp[i] = i−left ;
class Solution {
public static int lengthOfLongestSubstring(String s) {
//使用数组的动态规划实现方法
if(s.length()==0) return 0;
HashMap<Character,Integer> map=new HashMap<>();
int[] dp=new int[s.length()];
//初始化处理
map.put(s.charAt(0),0);
dp[0]=1;
//dp核心部分
int left=-1;//左侧边界
for(int i=1;i<s.length();i++) {
//每次更新得到的是s.charAt(i)两次出现对应的边界
if(map.containsKey(s.charAt(i))) left = Math.max(left,map.get(s.charAt(i)));//更新左边界
map.put(s.charAt(i),i);//更新索引
if(dp[i-1]<i-left) dp[i]=dp[i-1]+1;
else dp[i]=dp[i-1];
}
return dp[s.length()-1];
}
}
动态规划 2.0
思路与上一种方法一致,主要变化在于将数组改为tmp,降低了空间复杂度
class Solution {
public int lengthOfLongestSubstring(String s) {
HashMap<Character, Integer> dic = new HashMap<>();
int res = 0, tmp = 0;
for(int i = 0; i < s.length(); i++) {
int left = dic.getOrDefault(s.charAt(i), -1); // 获取左边界
dic.put(s.charAt(i), i); // 更新索引
//更新tmp
if( tmp<i-left ) tmp++;
else tmp = i-left;
//更新res
res = Math.max(res, tmp);
}
return res;
}
}
滑动窗口
滑动窗口的思路是每次求出该字符对应的子字符串的大小,若大于max则马上更新
class Solution {
public int lengthOfLongestSubstring(String s) {
HashMap<Character,Integer> dic = new HashMap<>();
int max = 0,start =-1;//划定当前窗口的坐标为(start,i],左开右闭,所以start的初始值为-1,而非0。
for(int i=0;i<s.length();i++){
//判断其索引值index和当前窗口start的大小以确定是否需要对start进行更新:
if( dic.containsKey(s.charAt(i)) ) start = Math.max( start, dic.get(s.charAt(i)) );
dic.put( s.charAt(i), i );//更新or新增键值对
//若当前滑动空间(start,i]的长度大于max,则进行更新。
max = Math.max( max, i-start );
}
return max;
}
}
HashMap
HashMap 是散列表,存储的内容是键值对(key-value)映射
构造方法:Map<Character, Integer> dic = new HashMap<>();
常见方法
- isEmpty()
- size()
- put() 将键/值对添加到 hashMap 中
- remove() 删除 hashMap 中指定键 key 的映射关系
- containsKey()
- containsValue()
- replace() 替换 hashMap 中是指定的 key 对应的 value。
- get() 获取指定 key 对应对 value
- getOrDefault() 获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值
- values() 返回 hashMap 中存在的所有 value 值。
- putAll()
- putIfAbsent()
- merge() 添加键值对到 hashMap 中
- compute() 对 hashMap 中指定 key 的值进行重新计算
- computeIfAbsent() 对 hashMap 中指定 key 的值进行重新计算,如果不存在这个 key,则添加到 hasMap 中
- computeIfPresent() 对 hashMap 中指定 key 的值进行重新计算,前提是该 key 存在于 hashMap 中。
- clear() 删除 hashMap 中的所有键/值对
- clone() 复制一份 hashMap
- replaceAll()
- forEach() 对 hashMap 中的每个映射执行指定的操作。