Leetcode:无重复字符的最长子串

普通版本(哈希表 + 滑动窗口)

题目链接:3. 无重复字符的最长子串 - 力扣(LeetCode)

//方法一:
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<char,int> st;
        int len = 0;
        int sz = s.size();
        for(int right = 0,left = 0; right < sz; right++)
        {
            if(st.find(s[right]) != st.end()) // 在哈希表中找到当前位置的字符
            {
                left = max(left, st[s[right]] + 1); // 更新左指针,加1避免重复字符
            }
            st[s[right]] = right; // 更新哈希表记录
            len = max(len, right - left + 1);//取之前记录的子字符串长度和right~left间的子字符串长度中的最大值
        }
        return len;
    }
};


方法二:
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<char, int> st;
        int len = 0; // 最终结果
        int tmp = 0;
        int sz = s.size();
        int left = 0;

        for(int right = 0; right < sz; right++) {
            if (st.find(s[right]) != st.end()  ) //用于保证st[s[right]] >= left
            {
                len = max(len, right - left);
                left = max(left,st[s[right]] + 1); // right遇到重复字符,更新left
            }
            st[s[right]] = right; // 更新哈希表
        }


        len = max(len, sz - left); // 处理只有一个空字符 或 没有字符的情况
  
        return len;
    }
};
  • 空格也是字符
  • right负责探路实际的子串是[left,right)
  • unordered_map的find返回值是迭代器不是布尔,调用[]返回的是对传入的键对应的值的引用
  • 使用unordered_map<char,int>是为了更好的更新left的位置,因为unordered_map不会出现重复字符,我们遇到相同字符时先用之前存好的重复位置更新+1使得left跳过该字符后(为了保证[left,rigth)间不会再有重复字符,如果只是left+1可能还会有重复字符),再更新重复字符的新位置(此时[left,right)中的字符都是不重复的)

 unordered_map<char,int> st可以回顾下map和set:C++的map和set-CSDN博客 

优化版本(动态规划 + 哈希表)

1、设动态规划列表dp,dp[ j ]代表以字符 s[ j ]为结尾的 “最长不重复子字符串” 的长度

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<char, int> st;
        int res = 0, tmp = 0, len = s.size(), i;
        for(int right = 0; right < len; right++) 
        {
            if (st.find(s[right]) == st.end()) 
                i = - 1;
            else 
                i = st.find(s[j])->second; // 获取索引 i
            st[s[right]] = right; // 更新哈希表
            tmp = tmp < right - i ? tmp + 1 : right - i; // dp[j - 1] -> dp[j]
            res = max(res, tmp); // max(dp[j - 1], dp[j])
        }
        return res;
    }
};

  • continue会使得程序跳过迭代表达式(也就是i++)

~over~

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值