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; }
我把部分算法题整理成了PDF文档,截止目前总共有900多页,大家可以下载阅读
链接:https://pan.baidu.com/s/1hjwK0ZeRxYGB8lIkbKuQgQ
提取码:6666