题解 | 最长不含重复字符的子字符串

最长不含重复字符的子字符串

https://www.nowcoder.com/practice/48d2ff79b8564c40a50fa79f9d5fa9c7

#include <unordered_map>
class Solution {
  public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param s string字符串
     * @return int整型
     */
    int lengthOfLongestSubstring(string s) {
        // write code here
        if(s.length()==0) return 0;
        //每个字母所在的位置,开始的位置,要换开始位置的时候才比较当前串和已经得到的最长串。
        int pos = 1, res = 0;
        unordered_map<char, int> ump;
        //string ans="";
        //string可以更改内容,不是const, char[] 固定了就不能改了,退化成指
        for (int i = 0; i < s.size(); ++i) {
            
            if (ump[s[i]] >= pos) {
                //发现重复的,如果没有改变就没有初始值
                res = max(res, (i + 1 - pos));
                pos = ump[s[i]]+1;//新pos
            }
            ump[s[i]] = i + 1;
        }
        int len = s.size();
        res = max(res, (len-pos+1));
        return res;
    }
};

对于这道题的直观感受就是要找到地址,然后通过是否上个地址在此次区间内来判定是否到下一个区间去。

所以我需要上个地址,和此区间的一个范围。

上个地址只有一个所以可以直接使用hash来存储,区间范围头部需要标定,在发生矛盾是转换,而尾部就是我们现在已经走到的坐标。

这里有两个问题,一个是转换条件,前面已经说了;一个是到尾部之后可能是最长的那一串但是没有记录了,所以要单独处理。

空间复杂度为O(1),时间复杂度为O(n)。

#include <unordered_map>
#include <vector>
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param s string字符串 
     * @return int整型
     */
    int lengthOfLongestSubstring(string s) {
        // write code here
        if(s.length()==0) return 0;
        int res = 0;
        unordered_map<char, int> mp;
        int len = s.length();
        vector<int> dp(len+1, 0);//int dp[len+1]; // 运行时确定长度,不被C++标准支持
        for(int i = 1; i <= s.length(); ++i){
            if(mp.count(s[i-1])==0){
                dp[i] = dp[i-1]+1;
            }
            else{
                dp[i] = min(dp[i-1]+1, i - mp[s[i-1]]);
            }
            mp[s[i-1]] = i;
            res = max(res, dp[i]);
        }
        return res;
    }
};

在思考这个问题的时候我并没有考虑到动态规划的做法,因为更小的部分很容易想到只是少一个的字符串,而上一个位置和它没有关系,那么这个转换其实并不方便。

但是官方题解给了一个很巧妙的东西,就是直接比较它和上一个直接加一的谁更短,因为如果上一个的范围不包括目前这个值的上一位,那么上一个范围+1就会比目前到上一个相同值的位置的距离更短。

这个代码我第一次写的时候用了int数组,想着运行时出结果可能过不了编译,结果居然过了(感觉是编译器原因,如GCC和Clang支持C99的变长数组作为编译器扩展。尽管这并不是C++标准的一部分)。

但是还是建议使用vector存储变长的数组,万一哪天碰到一个编译器启用了严格的C++标准模式呢。

全部评论

相关推荐

06-05 19:46
已编辑
武汉大学 后端
点赞 评论 收藏
分享
nus2201602...:兄弟,你这个简历撕了丢了吧,就是一坨,去找几个项目,理解项目流程,看几遍就是你的了,看看八股就去干了,多看看牛客里别人发出来的简历,对着写,你这写的啥啊,纯一坨
点赞 评论 收藏
分享
ohs的小木屋:比不少实习待遇高了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务