【问题描述】[第3题][无重复字符的最长字串]
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。示例 1:输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
【解答思路】
1. 滑动窗口之 HashMap
时间复杂度:O(N) 空间复杂度:O(N)
public int lengthOfLongestSubstring(String s) {int n = s.length();int ans = 0;Map<Character,Integer> map = new HashMap<>();for(int start=0,end=0; end < n ; end ++){char alpha = s.charAt(end);if(map.containsKey(alpha)){start = Math.max(map.get(alpha), start);}ans = Math.max(ans,end-start +1);//记录start应该调整到哪里map.put(s.charAt(end),end+1);}return ans;}
2. 滑动窗口之HashSet
时间复杂度:O(N) 空间复杂度:O(N)
public int lengthOfLongestSubstring(String s) {int n = s.length();Set<Character> set = new HashSet<>();int ans = 0, i = 0, j = 0;while (i < n && j < n) {// try to extend the range [i, j]if (!set.contains(s.charAt(j))){set.add(s.charAt(j++));ans = Math.max(ans, j - i);}else {set.remove(s.charAt(i++));}}return ans;}
class Solution {public int lengthOfLongestSubstring(String s) {// 哈希集合,记录每个字符是否出现过Set<Character> occ = new HashSet<Character>();int n = s.length();// 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动int rk = -1, ans = 0;for (int i = 0; i < n; ++i) {if (i != 0) {// 左指针向右移动一格,移除一个字符occ.remove(s.charAt(i - 1));}while (rk + 1 < n && !occ.contains(s.charAt(rk + 1))) {// 不断地移动右指针occ.add(s.charAt(rk + 1));++rk;}// 第 i 到 rk 个字符是一个极长的无重复字符子串ans = Math.max(ans, rk - i + 1);}return ans;}
}
2. 滑动窗口之 数组(本质HashMap)
时间复杂度:O(N) 空间复杂度:O(N)
public int lengthOfLongestSubstring(String s) {//128个字符 int[] m = new int[128];int len = 0;//i: start j:end for(int i = 0, j = 0; j < s.length(); j++){i = Math.max(m[s.charAt(j)], i);len = Math.max(len, j - i + 1);//记录i应该调整到哪里m[s.charAt(j)] = j + 1;}return len;}
【总结】
1. 滑动窗口思想 常用于字符数组题目中
- 更新start(+1)
- 边界思考清楚 start end 迭代
2.Java String 类
3.HashMap 或 HashSet常见用法
3.1 HashSet
(1)增加
public boolean add(E e);
(2)删除
public boolean remove(Object j);
(3)对比查找
public boolean contains(Object j);
(4)清空集合
public void clear();
(5)获取长度
public int size();
3.2 HashMap
(1) 插入键值对数据
public V put(K key, V value)
(2)根据键值获取键值对值数据
public V get(Object key)
(3)获取Map中键值对的个数
public int size()
(4)判断Map集合中是否包含键为key的键值对
public boolean containsKey(Object key)
(5)判断Map集合中是否包含值为value的键值对
boolean containsValue(Object value)
(6)判断Map集合中是否没有任何键值对
public boolean isEmpty()
(7)清空Map集合中所有的键值对
public void clear()
(8)根据键值删除Map中键值对
public V remove(Object key)