1,解法一
我们使用两个指针,一个i一个j,最开始的时候i和j指向第一个元素,然后i往后移,把扫描过的元素都放到map中,如果i扫描过的元素没有重复的就一直往后移,顺便记录一下最大值max
,如果i扫描过的元素有重复的,就改变j的位置,我们就以pwwkew
(这是之前画的图,求的是字符串,不是数字,这里就拿来用了,原理都是一样的)为例画个图看一下
代码如下
public int maxLength(int[] arr) {
if (arr.length == 0)
return 0;
HashMap<integer, integer> map = new HashMap<>();
int max = 0;
for (int i = 0, j = 0; i < arr.length; ++i) {
if (map.containsKey(arr[i])) {
j = Math.max(j, map.get(arr[i]) + 1);
}
map.put(arr[i], i);
max = Math.max(max, i - j + 1);
}
return max;
}
2,解法二
我们还可以用一个队列,把元素不停的加入到队列中,如果有相同的元素,就把队首的元素移除,这样我们就可以保证队列中永远都没有重复的元素
public int maxLength(int[] arr) {
//用链表实现队列,队列是先进先出的
Queue<integer> queue = new LinkedList<>();
int res = 0;
for (int c : arr) {
while (queue.contains(c)) {
//如果有重复的,队头出队
queue.poll();
}
//添加到队尾
queue.add(c);
res = Math.max(res, queue.size());
}
return res;
}
3,解法三
同样我们还可以使用集合set来代替队列,用两个指针,一个left一个right,如果有重复的就把left指向的给移除(left相当于队首,right相当于队尾)
public int maxLength(int[] arr) {
int maxLen = 0;
Set<integer> set = new HashSet<>();
int left = 0, right = 0;
while (right < arr.length) {
while (set.contains(arr[right]))
set.remove(arr[left++]);
set.add(arr[right++]);
maxLen = Math.max(maxLen, right - left);
}
return maxLen;
}
4,解法四
这里我们还可以改一下,把right-left改为set.size(),顺便再减少一层while循环
public int maxLength(int[] arr) {
int left = 0, right = 0, max = 0;
Set<integer> set = new HashSet<>();
while (right < arr.length) {
if (set.contains(arr[right])) {
set.remove(arr[left++]);
} else {
set.add(arr[right++]);
max = Math.max(max, set.size());
}
}
return max;
}