LeetCode 刷题记录 3. Longest Substring Without Repeating Characters

问题:
Given a string, find the length of the longest substring without repeating characters.

Example 1:

Input: “abcabcbb”
Output: 3
Explanation: The answer is “abc”, with the length of 3.
Example 2:

Input: “bbbbb”
Output: 1
Explanation: The answer is “b”, with the length of 1.
Example 3:

Input: “pwwkew”
Output: 3
Explanation: The answer is “wke”, with the length of 3.
Note that the answer must be a substring, “pwke” is a subsequence and not a substring.
答案:

方法1:暴力法 用一个map记录字母的次数
两重循环 第一重循环 首先将map清空: mapping.erase(mapping.begin(), mapping.end());
第二重循环 记录字母的次数 直到字母的次数为2 即检测到一个重复的字母,终止循环,记录长度并更新最大长度
maxAns的值赋值为0,处理空字符串的问题
C++版:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        
        unordered_map<char, int> mapping;
        int maxAns = 0;
        int i, j;
        for(i = 0; i < s.size(); i++){
            mapping.erase(mapping.begin(), mapping.end());
            mapping[s[i]]++;
            for(j = i + 1; j < s.size(); j++){
                mapping[s[j]]++;
                if(mapping[s[j]] == 2){
                    break;
                }
                
            }
            if((j - i) > maxAns){
                maxAns = (j - i);
            }
            
        }
        
           
        return maxAns;
    }
        
    
};

java:

  1. 不能用size而用length
  2. map操作用get和put函数 String 中的charAt函数得到的是字符,不能用s[i]
  3. map需要判断键是否存在 用containsKey函数
  4. map可以用clear
class Solution {
    public int lengthOfLongestSubstring(String s) {
        Map<Character, Integer> mapping = new HashMap<Character, Integer>();
        int maxAns = 0;
        int i, j;
        for(i = 0; i < s.length(); i++){
            mapping.clear();
            mapping.put(s.charAt(i), 1);
            for(j = i + 1; j < s.length(); j++){
                if(mapping.containsKey(s.charAt(j))){
                    mapping.put(s.charAt(j), mapping.get(s.charAt(j)) + 1);
                } else {
                    mapping.put(s.charAt(j), 1);
                }
                
                if(mapping.get(s.charAt(j)) == 2){
                    break;
                }
                
            }
            if((j - i) > maxAns){
                maxAns = (j - i);
            }
            
        }
        
           
        return maxAns;
    }
}

Python:
1.字典判断键是否存在用in
2.用len表示长度 并且Python中无++

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        mapping = {}
        maxAns = 0
        for i in range(len(s)):
            mapping.clear()
            
            mapping[s[i]] = 1
            
            j = i + 1
            while j < len(s):
                
                if s[j] in mapping:
                    mapping[s[j]] = mapping[s[j]] + 1
                else:
                    mapping[s[j]] = 1
                
                if mapping[s[j]] == 2:
                    break;
                j = j + 1
            if (j - i) > maxAns:
                maxAns = (j - i)
            
           
        return maxAns
    
        
    
    

方法2:滑动窗口法:
map记录字符最后出现的位置
维护一个滑动窗口 left是其左边界,右边界是当前访问的字符,初始化为-1
如果当前访问的字符已经出现过,如果在滑动窗口中,就需要删除该字符,即将left赋值为出现的字符的位置
如果不在滑动窗口则没事继续加进来
注意点:

  1. 更新最大长度必须在左边界更新后进行
  2. 除了判断字符是否出现过还要判断是否在当前滑动窗口
    例子:
    “abbb”
    初始化: left为-1,
    i=0,a未出现过,不更新left,记录位置a-> 0,窗口长度1
    i=1,b未出现过,不更新left,记录位置b->1,窗口长度2
    i=2,b出现过,位置为1,且出现过的b在窗口中,需要删除,即将left赋值为b最后的位置1,重新开始窗口,记录新的b位置为2,窗口长度为1
    i=3,a出现过,位置为0,但不知当前窗口中,继续加入窗口,新的a位置为3,窗口长度为2
    结束,最大长度为2

C++:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        
        //记录每个字符最后出现的位置
        unordered_map<char, int> mapping;
        //滑动窗口左边位置 它总在滑动窗口最左边字符的前一位,以便计算窗口长度,初始化为-1
        int left = -1;
        int maxAns = 0;
        for(int i = 0; i < s.size(); i++){
            
            //判断当前字符是否出现过 即mapping.count(s[i])是否为0,是0表示未出现,1表示出现过
            //如果该字符出现过且在滑动窗口中mapping[s[i]] > left
            //删除该字符,即将left赋值为出现的字符的位置
            if(mapping.count(s[i]) && mapping[s[i]] > left){
                left = mapping[s[i]];
            }
            mapping[s[i]] = i;//储存字符的位置无论是否出现过
            //更新最大长度
            maxAns = max(maxAns, i - left);
            
        }
        return maxAns;
        
    }
        
    
};

java:
max函数在Math类中

class Solution {
    public int lengthOfLongestSubstring(String s) {
        Map<Character, Integer> mapping = new HashMap<Character, Integer>();

        
          
        //滑动窗口左边位置 它总在滑动窗口最左边字符的前一位,以便计算窗口长度,初始化为-1
        int left = -1;
        int maxAns = 0;
        for(int i = 0; i < s.length(); i++){
            
            if(mapping.containsKey(s.charAt(i)) && mapping.get(s.charAt(i)) > left){
                left = mapping.get(s.charAt(i));
            }
            mapping.put(s.charAt(i), i);//储存字符的位置无论是否出现过
            //更新最大长度
            maxAns = Math.max(maxAns, i - left);
            
        }
        return maxAns;
    }
}

Python:

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        mapping = {}
        
        left = -1
        maxAns = 0
        for i in range(len(s)):
            
            if s[i] in mapping and mapping[s[i]] > left:
                left = mapping[s[i]]
            
            mapping[s[i]] = i
           
            maxAns = max(maxAns, i - left)
            
        
        return maxAns

解法3:
上个版本的精简版本
不用map存储位置而改用向量存储,总共存储256个字符,有ASCII码的字符总共有256个,全部初始化为-1
改动的位置:不用判断字符是否出现过,没出现过,位置初始化为-1,而left最小值为-1,故不可能大于left,因此不能进入条件语句中,所以不用判断
C++:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        
        vector<int> mapping(256, -1);
        //滑动窗口左边位置 它总在滑动窗口最左边字符的前一位,以便计算窗口长度,初始化为-1
        int left = -1;
        int maxAns = 0;
        for(int i = 0; i < s.size(); i++){
            
            
            //如果该字符出现过且在滑动窗口中mapping[s[i]] > left
            //删除该字符,即将left赋值为出现的字符的位置
            if(mapping[s[i]] > left){
                left = mapping[s[i]];
            }
            mapping[s[i]] = i;//储存字符的位置无论是否出现过
            //更新最大长度
            maxAns = max(maxAns, i - left);
            
        }
        return maxAns;
        
    }
        
    
};

java:
Arrays.fill函数给数组赋一样的值

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int[] mapping = new int[256];
        
        Arrays.fill(mapping, -1);
        
          
        //滑动窗口左边位置 它总在滑动窗口最左边字符的前一位,以便计算窗口长度,初始化为-1
        int left = -1;
        int maxAns = 0;
        for(int i = 0; i < s.length(); i++){
            
            if(mapping[s.charAt(i)] > left){
                left = mapping[s.charAt(i)];
            }
            mapping[s.charAt(i)] = i;//储存字符的位置无论是否出现过
            //更新最大长度
            maxAns = Math.max(maxAns, i - left);
            
        }
        return maxAns;
    }
}

Python:
Python ord() 函数将ASCII码转为整数 chr()函数将整数转为ASCII码

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        mapping = [-1] * 256
        
        left = -1
        maxAns = 0
        for i in range(len(s)):
            
            if mapping[(ord)s[i]] > left:
                left = mapping[(ord)s[i]]
            
            mapping[(ord)s[i]] = i
           
            maxAns = max(maxAns, i - left)
            
        
        return maxAns
    

方法4:
利用set去重的特点
把出现过的字符都放入set中,遇到set中没有的字符就加入set中并更新结果,如果遇到重复的,则从左边开始删字符,直到删到重复的字符停止,
例如“abba”
初始i为0,left也为0
i=0,set中没有a,加入a,更新最大长度,i向后移动
i=1,set中没有b,加入b,更新最大长度,i向后移动
i=2,set中有b,开始删从left删字符,先删a,left为1,set还剩b,此时依然重复,继续删b,left =2,set没有重复的元素,然后将s[2]=b,加入进来,更新最大长度,i向后移动
i=3,set中没有a,加入a,更新最大长度,i向后移动
C++:
unordered_set以散列替代了红黑树,速度更快,但是没有了排序功能
set中erase函数既可以传删除元素的迭代器也可以传要删除的值
(int)mapping.size()要做类型转换

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        
        unordered_set<char> mapping;
        
        int left = 0;
        int maxAns = 0;
        int i = 0;
        while(i < s.size()){
            
            if(!mapping.count(s[i])){
                
                mapping.insert(s[i++]);
                maxAns = max(maxAns, (int)mapping.size());
            } else {
                mapping.erase(s[left++]);
            }
            
            
            
        }
        return maxAns;
        
    }
        
    
};

java:
java中set string 首字母都是大写Set String
Set中查看是否存在用contains函数
加入元素用add函数 删除用remove函数
String中是length函数 Set是size函数

class Solution {
    public int lengthOfLongestSubstring(String s) {
        Set<Character> mapping = new HashSet<Character>();
        
        int left = 0;
        int maxAns = 0;
        int i = 0;
        while(i < s.length()){
            
            if(!mapping.contains(s.charAt(i))){
                
                mapping.add(s.charAt(i++));
                maxAns = Math.max(maxAns, mapping.size());
            } else {
                mapping.remove(s.charAt(left++));
            }
            
            
            
        }
        return maxAns;
        
    }
}

Python:
可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        mapping = set()
        
        left = 0
        maxAns = 0
        i = 0
        while i < len(s):
            
            if s[i] not in mapping:
                
                mapping.add(s[i])
                i = i + 1
                maxAns = max(maxAns, len(mapping))
            else:
                mapping.remove(s[left])
                left = left + 1
            
            
            
        
        return maxAns
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值