力扣3.无重复字符的最长子串

题目:传送门
题意: 给定一个字符串,这个字符串由英文字母数字符号空格组成,找出字符串中不含有重复字符最长子串,题意很简单,思路也很简单,只需要遍历一遍字符串,找到两个相同的字符,他们的下标之差就是一个不含有重复字符的子串,再从符合条件的子串中选出最长的一个子串即可。

如何标记字符是否出现呢?我最开始的思路是用一个数组,用字符的ASCII当做下标,这样也是可以的,开辟一个150的数组,因为ASCII只有127位,这样是可以的,但是我没有用数组,而是使用map函数,使用map<char,int>p,用字符当做下标,用字符在字符中的位置当做值,形成一种映射关系,更加方便。

接着分析字符串的情况,第一种情况,“abcdefg”,字符串中没有重复字符,这种情况最为简单,就只需要让字符的相对位置,下标+1减去f开始的起始位置,例如循环遍历到字符’c’,f=0,相对位置2+1=3,这个时候最长子串就是3-0=3;
第二种情况,“abcabcabcbb”,这种情况就是两个重复字符之间没有其他重复字符,例如"abca",两个’a’之间没有其它重复字符,那么这种情况如何求长度呢,就只需要用第二个’a’的相对位置4-第一个’a’的相对位置1=3;
第三种情况,“abcba”,这种情况就是两个重复字符之间有其它重复字符,前两种情况都可以用当前字符的下标+1-map的值或者f,但是这种情况,我就要更新f的值,“abcba”,当第二个‘a’的时候,f的位置应该是字符c的相对位置,就是重复字符b的相对位置。
上代码:

class Solution {
    
    
public:
    int lengthOfLongestSubstring(string s) {
    
    
        int ans=0,f=0;
        map<char,int >p;
        for(int i=0;i<s.size();i++){
    
    
            int x=p[s[i]],flag;
            if(x!=0)//判断当前字符有没有出现过
                 f=max(f,x);//如果当前字符出现过,那么就要更新f的值,更新字符子串开始的位置
            flag=i+1-f;
            p[s[i]]=i+1;//更新map的值,用当前字符位置覆盖之前重复的位置
            ans=max(ans,flag);
        }
        return ans;
    }
};

Guess you like

Origin blog.csdn.net/qq_43840681/article/details/117325818