力扣 3.无重复字符的最长子串(滑动窗口)

#include <iostream>
#include <string>
#include <unordered_set>
#include <algorithm>

using namespace std;

int lengthOfLongestSubstring(string s) {
    size_t n = s.length();  // 使用 size_t 类型来匹配字符串长度的类型
    unordered_set<char> charSet;
    int maxLength = 0, left = 0, right = 0;

    while (right < n) {
        // 如果字符已经在集合中,移动左指针,缩小窗口直到窗口内不含重复字符
        while (charSet.count(s[right])) {
            charSet.erase(s[left]);
            left++;
        }
        // 将当前字符加入集合
        charSet.insert(s[right]);
        // 更新最大长度
        maxLength = max(maxLength, static_cast<int>(right - left + 1));
        // 移动右指针扩大窗口
        right++;
    }

    return maxLength;
}

int main() {
    string s;
    cout << "Enter a string: ";
    getline(cin, s);  // 使用 std::getline 获取用户输入的字符串

    int result = lengthOfLongestSubstring(s);
    cout << "Length of the longest substring without repeating characters: " << result << endl;

    return 0;
}

滑动窗口

如果没有很直观的理解可以先从暴力入手

#include <iostream>
#include <string>
#include <unordered_set>

using namespace std;

int lengthOfLongestSubstring(string s) {
    int maxLength = 0;
    int n = s.length();

    // 遍历所有可能的子串
    for (int i = 0; i < n; ++i) {
        unordered_set<char> charSet;
        for (int j = i; j < n; ++j) {
            // 如果当前字符已经在集合中,说明有重复字符,结束内层循环
            if (charSet.count(s[j])) {
                break;
            }
            // 否则将当前字符加入集合中
            charSet.insert(s[j]);
            // 更新最大长度
            maxLength = max(maxLength, j - i + 1);
        }
    }

    return maxLength;
}

int main() {
    string s = "abcabcbb";
    cout << lengthOfLongestSubstring(s) << endl; // 输出:3

    s = "bbbbb";
    cout << lengthOfLongestSubstring(s) << endl; // 输出:1

    s = "pwwkew";
    cout << lengthOfLongestSubstring(s) << endl; // 输出:3

    return 0;
}

这两个代码特点都是运用了哈希表存储来判别是否存在重复的字符,滑动窗口则是更高效,并且是双指针遍历并且是动态进行。

下面是对滑动窗口的一些讲解

滑动窗口算法通常被视为双指针技术的一种动态应用形式。虽然“滑动窗口”和“双指针”可以用于描述不同的场景,但它们有许多共同点和重叠的地方。以下是对两者的解释及其联系:

双指针技术

双指针技术涉及在数据结构中使用两个指针,常见于解决以下类型的问题:

  • 两个指针向中间收敛:如在排序数组中查找两数之和、反转字符串等。
  • 一个指针遍历,一个指针调整:如在链表中查找倒数第k个节点等。

滑动窗口技术

滑动窗口是一种动态的双指针应用,特别适用于处理连续子数组或子串的问题。滑动窗口技术通过调整窗口的起点和终点来动态地包含或排除元素,从而满足特定的条件。滑动窗口的两个边界可以看作是两个指针,这些指针可以独立移动以扩大或缩小窗口。

"滑动指针"通常可以被理解为一种特殊的"双指针"技术。虽然这两者的名字有所不同,但它们的核心思想和实现方式非常相似,都是通过调整指针或窗口的位置来解决问题。

滑动指针与双指针的联系和区别

  1. 滑动指针

    • 滑动指针可以看作是一种更为灵活的双指针技术,通常用于处理连续子数组或子串的问题。
    • 它的动态性体现在可以根据具体问题,每次移动一个窗口的起始或结束位置,来寻找最优解。
    • 滑动指针的移动不一定是每次移动一个固定步长,而是根据问题需要在集合中移动窗口边界。
  2. 双指针

    • 双指针通常指的是同时在数据结构中移动两个指针,例如数组或链表。
    • 这两个指针通常用于解决某些特定类型的问题,如反转数组、查找两数之和等。
    • 在双指针技术中,指针的移动往往是固定的步长,并且往往是沿着数据结构的方向进行移动。

维护滑动指针的基本方法

维护滑动指针的关键是根据问题的要求,调整窗口的大小和位置,以便在数据结构中找到所需的子数组或子序列。以下是一般情况下维护滑动指针的方法:

  • 初始化:定义需要用到的指针和集合(或其他适合的数据结构)。
  • 移动窗口
    • 根据问题的要求,移动窗口的起始或结束位置。
    • 根据集合的变化(添加或删除元素),来动态调整窗口的大小和位置。
  • 更新状态:根据窗口的变化,计算或更新所需的状态或结果。

具体来说,如果需要动态调整滑动窗口的指针,可以根据当前集合中的情况,适时地移动窗口的边界。例如,在求解最长不含重复字符的子串时,如果发现重复字符,可以移动窗口的起始指针,直到窗口内不再有重复字符。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值