java实现寻找最长无重复字符的子字符串

文章介绍了如何使用Java的滑动窗口算法来寻找字符串中的最长无重复字符子串,方法包括维护两个指针start和end,以及使用一个布尔数组seen记录字符出现情况。该算法具有O(n)的时间复杂度和O(1)的空间复杂度。
摘要由CSDN通过智能技术生成

用java实现寻找最长无重复字符的子字符串(滑动窗口算法详解)

一、用java实现寻找最长无重复字符的子字符串

其中一种常见的方法是使用滑动窗口(sliding window)的技巧,即维护一个不含重复字符的子字符串,并用两个指针(start和end)表示其起始和结束位置。然后遍历整个字符串,每次将end指针向右移动一位,并检查当前字符是否已经在窗口中出现过。如果出现过,就将start指针向右移动到重复字符的下一个位置,并更新窗口。同时,记录下每次窗口的长度,并与最大长度进行比较,最后返回最大长度。

使用这种方法,可以在O(n)的时间复杂度和O(1)的空间复杂度内完成任务。

public int lengthOfLongestSubstring(String s) {
    // 如果字符串为空或者长度为0,直接返回0
    if (s == null || s.length() == 0) {
        return 0;
    }
    // 定义两个指针start和end表示滑动窗口的起始和结束位置
    int start = 0;
    int end = 0;
    // 定义一个数组来记录每个字符是否在窗口中出现过
    boolean[] seen = new boolean[256];
    // 定义一个变量来存储最大长度
    int maxLength = 0;
    // 遍历整个字符串
    while (end < s.length()) {
        // 获取当前字符对应的ASCII码值
        int c = s.charAt(end);
        // 如果当前字符已经在窗口中出现过,就将start指针向右移动到重复字符的下一个位置,并更新seen数组
        while (seen[c]) {
            seen[s.charAt(start)] = false;
            start++;
        }
        // 将当前字符标记为已经出现过,并将end指针向右移动一位
        seen[c] = true;
        end++;
        // 计算当前窗口的长度,并与最大长度进行比较,更新maxLength
        maxLength = Math.max(maxLength, end - start);
    }
    // 返回最大长度
    return maxLength;
}

二、滑动窗口算法详解

滑动窗口算法是一种常用的优化技巧,可以用来解决一些涉及数组或字符串的问题¹²³⁴⁵⁶。它的基本思想是维护一个连续的子数组或子字符串,称为窗口,并用两个指针(start和end)表示其起始和结束位置。然后根据题目要求,移动这两个指针来调整窗口的大小和位置,并在每次移动后更新所需的结果。

使用滑动窗口算法的好处是可以避免使用嵌套循环,从而降低时间复杂度。通常,滑动窗口算法可以将O(n2)或O(n3)的暴力解法优化为O(n)或O(n log n)的高效解法。

滑动窗口算法是一种在数组或字符串上执行操作的技术,它可以用一个固定大小的窗口来覆盖数组或字符串的一部分,然后不断地向前移动窗口,直到遍历完整个数组或字符串。¹²

滑动窗口算法可以将嵌套的循环问题转换为单循环问题,降低时间复杂度。⁴⁵

滑动窗口算法通常用双指针来实现,一个指针表示窗口的左端,另一个指针表示窗口的右端。根据题目的要求,可以调整窗口的大小和移动方式。³⁶

滑动窗口算法有很多应用场景,比如求解最长不重复子串、最小覆盖子串、最大连续子数组和等等。

滑动窗口算法也有一些变体,比如可以使用双端队列来实现窗口的更新,或者使用哈希表来存储窗口内的元素和频率。

下面我给你看一个滑动窗口算法的例题和代码吧。

题目:给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

代码(Java):

class Solution {
    public int lengthOfLongestSubstring(String s) {
        // 使用哈希集合来存储窗口内的字符
        //这行代码创建了一个名为set的新变量,它是一个Set类型的对象。
        //Set是Java集合框架中的一种接口,它表示一组不包含重复元素的元素。
        //HashSet是Set接口的一个实现,它使用哈希表作为其内部实现。
        //这行代码创建了一个新的HashSet对象,并将其分配给set变量。这个HashSet对象将用于存储Character类型的元素。
        Set<Character> set = new HashSet<>();
        // 定义左右指针和最大长度
        int left = 0, right = 0, maxLen = 0;
        // 遍历字符串
        while (right < s.length()) {
            // 取出右指针指向的字符
            char c = s.charAt(right);
            // 如果该字符已经在集合中,说明出现了重复,需要缩小窗口
            while (set.contains(c)) {
                // 从集合中移除左指针指向的字符
                set.remove(s.charAt(left));
                // 左指针右移一位
                left++;
            }
            // 如果该字符不在集合中,说明没有重复,可以扩大窗口
            // 将该字符加入集合中
            set.add(c);
            // 右指针右移一位
            right++;
            // 更新最大长度为当前窗口大小
            maxLen = Math.max(maxLen, right - left);
        }
        return maxLen;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值