Problem: 3. 无重复字符的最长子串
思路
此题没有思路. 是看题解做的.
很多时候,看完题后没有任何思路,因为我没有见过类似题型.
所以先思考,没有思路就看题解. 埋头硬想只会失去战斗力.
把题解中的变量命名规范一下,更容易理解.
解题方法
- 字符串转换成字符数组.
- 定义一个 hashMap, 值作为key, 下标作为value.
- 初始化最大总长度 maxCount = 0, 左指针下标为0.
- 遍历数组,下标记为rigthIndex,
- 如果当前值在 map中存在, 说明出现重复字符了. 需要把左指针移动到重复字符的右边.
- 将当前值及当前下标添加到map中.
- 计数并和最大长度MaxCount对比,并赋值.
难点
第5步为什么要用leftIndex=Math.max(leftIndex,map.get(rightValue)+1);
而不是直接用leftIndex=map.get(rightValue)+1;
答:在滑动窗口中,左指针只能往右走,不准往后退.
举个容易理解的例子: str=“abba”;
如果不加Math.max, 当右指针下标为3时, 左指针为0. 此时 下标1和下标2重复. 导致错误结果maxCount为3.
如果加了Math.max, 前几轮已经排除了重复数值’b’和’b’.左下标移动到了2, 使用max,保证了下标不会倒回去.
语言表达能力有限,如果理解不了,建议debugger一下就明白了
复杂度
时间复杂度:
应该是O(n)吧
空间复杂度:
算不来
Code
class Solution {
public int lengthOfLongestSubstring(String str) {
//1 转成数组
char[] array = str.toCharArray();
//2 创建map保存字符.
HashMap<Character, Integer> map = new HashMap<>();
//3 定义左指针下标
int leftIndex = 0;
//3 定义不重复字符串的长度
int maxCount = 0;
//4遍历数组(使用右指针)
for (int rigthIndex = 0; rigthIndex < array.length; rigthIndex++) {
//获取右指针对应的值
char rightValue = array[rigthIndex];
//如果当前值(右指针指向) 已经在map中存在了.
if (map.containsKey(rightValue)){
//5左指针指向map中重复的值.
//注意: 此时应该注意的,左指针只能往右走, 不能倒着走. 所以使用Math.max判断,是不是倒着走了. 比如 abba 当右指针指向 下标为3的'a'时, 从map中可以查询到下标0的'a', 此时如果将下标移动到 1 那么后边刚刚bb重复,相当于白做了.
leftIndex=Math.max(leftIndex,map.get(rightValue)+1) ;
}
//6将右指针的值和下标放进map中
map.put(rightValue,rigthIndex);
//7替换最大值.
maxCount = Math.max(maxCount,rigthIndex-leftIndex+1);
}
return maxCount;
}
}