Leetcode 3. 无重复字符的最长子串 做题小结

题目:

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:

输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:

输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

思路:

滑动窗口法:

思路和算法

我们先用一个例子来想一想如何在较优的时间复杂度内通过本题。

我们不妨以示例一中的字符串 exttt{abcabcbb}abcabcbb 为例,找出 从每一个字符开始的,不包含重复字符的最长子串,那么其中最长的那个字符串即为答案。对于示例一中的字符串,我们列举出这些结果,其中括号中表示选中的字符以及最长的字符串:
在这里插入图片描述

在这里插入图片描述
判断重复字符

在上面的流程中,我们还需要使用一种数据结构来判断 是否有重复的字符,常用的数据结构为哈希集合(即 C++ 中的 std::unordered_set,Java 中的 HashSet,Python 中的 set, JavaScript 中的 Set)。在左指针向右移动的时候,我们从哈希集合中移除一个字符,在右指针向右移动的时候,我们往哈希集合中添加一个字符。

至此,我们就完美解决了本题。

代码如下:

public int lengthOfLongestSubstring(String s) {
		 
		int ans = 0;
		int rk=0;
		HashSet<Character> occ = new HashSet<Character>();
		for(int i=0;i<s.length();i++) {
			if(i!=0) {
				occ.remove(s.charAt(i-1));
			}
			while(rk<s.length() && !occ.contains(s.charAt(rk))) {
				occ.add(s.charAt(rk));
				rk++;				
			}
			ans = Math.max(ans, rk-i);	
		}
		System.out.println(ans);
		return ans;
	}

知识点小结:

这里使用了HashSet创建了character的数组,先让我们了解一下HashSet
HashSet是基于HashMap来实现的,
是一个不允许有重复元素的集合,但是HashSet允许有空值。另外HashSet是无序的,
即不会记录插入的顺序。在线程安全方面,它也不是线程安全的,
如果多个线程尝试同时修改HashSet,则最终的结果是不正确的。
在多线程访问时,必须显式同步对HashSet的并发访问。

一个原因是HashSet创建的数组有remove方法,移除的是元素,不是下标。
而使用ArrayList无法使用remove直接移除数组的元素
原文地址:https://www.cnblogs.com/nmydt/p/14256401.html