牛客-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. 最长不含重复字符的子字符串

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值