牛客-NC41-最长无重复子数组



方法一:HashSet+滑动窗口

思路:一道滑动窗口题(纯暴力是会超时的,注意看上图的备注信息。),其实很好理解:我们要找最长且无重复的子数组,无重复需要使用HashSet进行去重。要找到最长的,可以使用滑窗的思想去动态地改变长度。有以下情况(1)没有重复数组元素时,right指针一直往右移动,同时更新maxLen和window表。(2)当出现重复数组元素时,我们需要移除left指针所对应的元素,同时移动left指针,知道当前window表中不再出现重复元素(这里没有更新maxLen的原因是right指针没变,left在往右移动,所以此时形成的子数组长度肯定小于maxLen)。于是可以写出如下代码:

import java.util.*;


public class Solution {
   
    /** * * @param arr int整型一维数组 the array * @return int整型 */
    public int maxLength (int[] arr) {
   
        // write code here
        // 特判
        int n = arr.length;
        if (n <= 1) return n;
        int maxLen = 1;
        
        int left = 0, right = 0;
        HashSet<Integer> window = new HashSet<>();
        while (right < n) {
   
            while (window.contains(arr[right])) {
   
                window.remove(arr[left]);
                left++;
            }
            maxLen = Math.max(maxLen, right - left + 1);
            window.add(arr[right]);
            right++;
        }
        return maxLen;
    }
}

时间复杂度: O(N), 最坏情况是left和right都遍历了一遍字符串。
空间复杂度: O(N), 我们需要window表来存放遍历到的值。

方法二:HashSet+滑动窗口(优化)

思路:对方法一做以下优化:当窗口存在重复元素,是一个一个元素的缩小窗口,可以使用HashMap记住每个元素在数组中的索引,当遇到重复元素时,可以直接跳到重复元素的后面。

import java.util.*;


public class Solution {
   
    /** * * @param arr int整型一维数组 the array * @return int整型 */
    public int maxLength (int[] arr) {
   
        // write code here
        // 当窗口存在重复元素,是一个一个元素的缩小窗口。
        // 可以使用hashmap记住每个元素在数组中的索引,当遇到重复元素时,可以直接跳到重复元素的后面。
        int n = arr.length;
        if (n <= 1) return n;
        int maxLen = 1;

        int left = 0, right = 0;
        HashMap<Integer, Integer> window = new HashMap();
        while (right < n) {
   
            Integer rightIndex = window.getOrDefault(arr[right], -1);
            left = Math.max(left, rightIndex + 1);
            maxLen = Math.max(maxLen, right - left + 1);
            window.put(arr[right], right);
            right++;
        }
        return maxLen;
    }
}

时间复杂度: O(N), 最坏情况是left和right都遍历了一遍字符串。
空间复杂度: O(N), 我们需要window表来存放遍历到的值。
总结:本题自己想到使用滑窗和set来解决,写到后面对于当遇到重复元素怎么处理犯了愁。不知道left和right指针怎么移动才是正确的,没想到是只需要移动left指针,right指针是不能动的。通过移动left指针来让该窗口中没有重复的数组元素,达到去重的目的。另外,这里给出LeetCode上两道与之解法相近的题目,分别是无重复字符的最长子串以及剑指 Offer 48. 最长不含重复字符的子字符串

全部评论

相关推荐

不愿透露姓名的神秘牛友
11-27 10:46
点赞 评论 收藏
分享
点赞 评论 收藏
分享
11-03 14:38
重庆大学 Java
AAA求offer教程:我手都抬起来了又揣裤兜了
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务