剑指 Offer 48. 最长不含重复字符的子字符串

剑指 Offer 48. 最长不含重复字符的子字符串 - 力扣(LeetCode) (leetcode-cn.com)

目录

解法1:滑动窗口

运行结果

思路

代码

解法2:动态规划

运行结果

 思路

代码


解法1:滑动窗口

运行结果

思路

设置一个窗口,窗口中的所有字符均不相重复,维护窗口的leftSide和rightSide。leftSide和rightSide初始化均为0,每次扩展窗口的rightSide(++rightSide),并检测rightSide位置的字符:

1. 如果和窗口中的任意字符均不重复,那么直接将rightSide位置的字符纳入窗口;

2. 如果和窗口中pos位置的字符重复了,那么更新窗口:leftSide = pos + 1,把pos及之前位置的字符均从窗口中排除掉,把rightSide位置的字符纳入窗口。

设置一个数组pos来记录窗口中每个字符在字符串中的位置,ASCII码总共只有128个,就算每个字符都在字符串中出现,记录它们的位置也不过128 * 4B即0.5KB,空间开销不大,因此完全可以开一个长度为128的数组。

rightSide位置的字符出现在窗口中(和某个位置的字符重复):pos[s[rightSide]] >= leftSide;

把rightSide位置的字符纳入窗口:pos[s[rightSide]] = rightSide;

代码

class Solution {
#define scale 0x7f
public:
    int lengthOfLongestSubstring(string s) {
        int pos[scale];
        for (int i = 0; i != scale; ++i) pos[i] = -1;

        int L = s.length();
        int leftSide = 0, len, max_len = 0;
        for (int rightSide = 0; rightSide != L; ++rightSide) {
            if (pos[s[rightSide]] >= leftSide) {
                len = rightSide - leftSide;
                len > max_len ? max_len = len : NULL;
                leftSide = pos[s[rightSide]] + 1;
            }
            pos[s[rightSide]] = rightSide;
        }
        return max(max_len, L - leftSide);
    }
};

解法2:动态规划

运行结果

 思路

我们用len[i]来表示以s[i]为结尾的最长不重复子串的最大长度,考虑len[i]和len[i-1]的关系。如果s[i]没有在以s[i-1]为结尾的最长不重复子串中出现,那么len[i] = len[i-1] + 1;如果s[i]出现在了以s[i-1]为结尾的最长不重复子串中,那么len[i] = 两个重复字符之间的距离。

使用一个数组pos来记录各个字符上次在字符串中出现的位置,数组元素初始化为-1.

代码

class Solution {
#define scale 0x7f
public:
    int lengthOfLongestSubstring(string s) {
        int pos[scale];
        for (int i = 0; i != scale; ++i) pos[i] = -1;

        int L = s.length();
        int len = 0, max_len = 0;
        for (int i = 0; i != L; ++i) {
            int d = i - pos[s[i]];
            len = d > len ? len + 1 : (len > max_len ? max_len = len : NULL, d);
            pos[s[i]] = i;
        }
        return max(len, max_len);
    }
};

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值