leetcode
leetcode 2751 ~ 2800
每个字符最多出现两次的最长子字符串

每个字符最多出现两次的最长子字符串

难度:

标签:

题目描述

Given a string s, return the maximum length of a substring such that it contains at most two occurrences of each character.

 

Example 1:

Input: s = "bcbbbcba"

Output: 4

Explanation:

The following substring has a length of 4 and contains at most two occurrences of each character: "bcbbbcba".

Example 2:

Input: s = "aaaa"

Output: 2

Explanation:

The following substring has a length of 2 and contains at most two occurrences of each character: "aaaa".

 

Constraints:

  • 2 <= s.length <= 100
  • s consists only of lowercase English letters.

代码结果

运行时间: 35 ms, 内存: 16.0 MB


/*
 * 思路:使用Java Stream的方式,虽然Stream更偏向于函数式编程,处理状态相关的滑动窗口问题比较复杂,
 * 所以这里依然用迭代方式来处理窗口滑动,只是尽量利用Stream API来处理其他部分。
 */

import java.util.HashMap;
import java.util.Map;
import java.util.stream.IntStream;

public class LongestSubstringWithMaxTwoOccurrencesStream {
    public static int findLongestSubstring(String s) {
        Map<Character, Integer> charCount = new HashMap<>();
        final int[] maxLength = {0};
        final int[] start = {0};

        IntStream.range(0, s.length()).forEach(end -> {
            char endChar = s.charAt(end);
            charCount.put(endChar, charCount.getOrDefault(endChar, 0) + 1);

            while (charCount.get(endChar) > 2) {
                char startChar = s.charAt(start[0]);
                charCount.put(startChar, charCount.get(startChar) - 1);
                start[0]++;
            }

            maxLength[0] = Math.max(maxLength[0], end - start[0] + 1);
        });

        return maxLength[0];
    }

    public static void main(String[] args) {
        System.out.println(findLongestSubstring("bcbbbcba")); // 输出: 4
        System.out.println(findLongestSubstring("aaaa")); // 输出: 2
    }
}

解释

方法:

该题解采用了滑动窗口的方法。首先定义一个哈希表来记录窗口内各字符的出现次数,以及一个变量来记录最大子字符串的长度。通过一个右指针遍历字符串,并在哈希表中更新该字符的出现次数。如果字符的出现次数超过2,即不满足题目要求,此时通过移动左指针减少该字符的计数,直到该字符的出现次数不超过2。在每次右指针移动后,更新最大长度。这样,当右指针遍历完整个字符串后,可以得到满足条件的最长子字符串的长度。

时间复杂度:

O(n)

空间复杂度:

O(1)

代码细节讲解

🦆
在滑动窗口方法中,如何有效地处理字符的计数以确保每次循环的效率?
在滑动窗口方法中,使用哈希表来跟踪窗口内每个字符的计数是处理字符计数的有效方式。每当右指针向右移动时,对当前字符的计数增加1;如果字符计数超过2,左指针向右移动,同时对移出窗口的字符的计数减少1。这种方式确保了每个字符的计数操作仅涉及常数时间复杂度O(1),从而使整体循环的效率得到保证。
🦆
哈希表在此问题中充当什么角色,为什么选择哈希表作为数据结构来存储字符计数?
在此问题中,哈希表用于存储和跟踪窗口内每个字符的出现次数。选择哈希表是因为它提供了快速的插入、删除和查找操作,每个操作平均时间复杂度为O(1)。这使得在滑动窗口算法中,对字符计数的更新和查询可以迅速进行,从而有效地维护和调整窗口大小以满足题目的要求。
🦆
当字符的出现次数超过2次,为什么只需要移动左指针来减少字符的计数,而不考虑其他可能的字符?
当字符的出现次数超过2次时,这意味着窗口内该字符的数量已不符合题目要求。移动左指针(减少窗口的左边界)是解决这一问题的直接方法,因为它可以减少这个超限字符的计数,直至其符合要求。不需要考虑其他字符的原因是,其他字符的出现次数在此时都符合要求(即不超过2次),因此只需调整超过限制的那个字符。这种策略简化了问题的处理,确保了算法的效率。

相关问题