NC41 最长无重复子数组

找到字符串的最长无重复字符子串

http://www.nowcoder.com/questionTerminal/b56799ebfd684fb394bd315e89324fb4

方法一:滑动窗口法

算法思路

我们可以利用双指针模拟一个滑动窗口。初始化该窗口为(left, right]。所以left从-1开始。窗口不断往右扩大。因为我们要的是无重复子数组,因此,遇到有重复的数字,在窗口左侧进行缩小。
在每次滑动时,对窗口的大小进行比较,保留最大的长度。
图片说明

图片说明

代码实现

import java.util.*;


public class Solution {
    /**
     * 
     * @param arr int整型一维数组 the array
     * @return int整型
     */
    public int maxLength (int[] arr) {
        // write code here
        if(arr.length < 2){
            return arr.length;
        }

        HashMap<Integer, Integer> windows = new HashMap<>();
        int res = 0;
        //用双指针来模拟一个滑动窗口
        int left = -1;
        //窗口向右滑动
        for(int right = 0; right < arr.length; right++){
            //遇到重复数字
            if(windows.containsKey(arr[right])){
                //因为有可能遇到的重复数字的位置 比 left还要前
                //所以不能把left置于该位置前一位, 而是比较哪个最大,目的还是为了缩小窗口
                //确保窗口内全是不重复的数字
                left = Math.max(left, windows.get(arr[right]));
            }
            //每次更新窗口大小
            res = Math.max(res, right-left);
            //将数字位置更新到windows中
            windows.put(arr[right], right);
        }
        return res;
    }
}

算法复杂度

  • 时间: O(n) n为数组的长度
  • 空间:O(n) n为HashMap的长度。

方法二:双指针 + 回头遍历

算法思路

定义双指针, right指针对数组进行遍历,left指针对arr[right]前的子数组进行遍历。当left小于0或者遇到重复数字时,终止left遍历。
定义res代表最长的长度,tmp代表当前字符拥有的子串长度。
每次更新tmp时,也得更新res。

代码实现

import java.util.*;


public class Solution {
    /**
     * 
     * @param arr int整型一维数组 the array
     * @return int整型
     */
    public int maxLength (int[] arr) {
        // write code here
        int res = 0, tmp = 0;
        for(int right = 0; right < arr.length; right++){
            int left = right -1;
            //回头遍历
            while(left >= 0 && arr[right] != arr[left]){
                left --;
            }
            //若指针距离比上一个字符拥有的子串长度要大,就tmp+1 否则说明,遇到了重复数字,设置为新的指针距离,方便下一步res比较
            tmp = tmp < right - left ? tmp + 1 : right - left;
            //更新res指
            res = Math.max(res, tmp);
        }
        return res;
    }
}

算法复杂度

  • 时间: O(n*n)
  • 空间: O(1)
CS-Review 文章被收录于专栏

本专栏记录本人维护的仓库( cs-review.cn )分类刷题解法~

全部评论
//因为有可能遇到的重复数字的位置 比 left还要前 //所以不能把left置于该位置前一位, 而是比较哪个最大,目的还是为了缩小窗口 //确保窗口内全是不重复的数字 哪种情况啊?????????
1 回复 分享
发布于 2021-08-25 14:28
class Solution: def maxLength(self , arr: List[int]) -> int: # write code here if len(arr) < 2: return len(arr) windows = {} res = 0 left = -1 for right in range(len(arr)): if arr[right] in windows: left = max(left, windows[arr[right]]) res = max(res, right - left) windows[arr[right]] = right return res
1 回复 分享
发布于 2021-11-25 10:22
滑动窗口有点难理解,但是可以看懂
点赞 回复 分享
发布于 2022-01-17 11:36
淦,用了动态规划。怪不得做出来排名这么后
点赞 回复 分享
发布于 2022-01-24 22:37

相关推荐

点赞 评论 收藏
分享
37 10 评论
分享
牛客网
牛客企业服务