LeetCode-3-无重复字符的最长子串-Java&Python

9 篇文章 0 订阅
9 篇文章 0 订阅

1.题目

https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/

2、实现

   Java

   数据结构:hashmap,key的唯一性

   思路:滑动窗口 ,map的(key,value)存放string s的(s.charAt(i),i),map的key是唯一的,但是put相同key的value1,会更新。用start表示字符串的开始位置,i为当前游标,如果当前字符 s.charAt(i) 已经存在map的keySet中,并且当前的start不大于s.charAt(i) 对应的map中存在的之前添加的Preindex (map.get(s.charAt(i))),就把start滑动到Preindex后一位

即,如果 s[i]在 [start ,i) 范围内有与之重复的字符s[i′ ], 我们直接跳过 [start,i'] 范围内的所有元素,并将 start 变为 i' + 1

写法一:增加显示判断 strat<=i' ,并且只有在start改变时,ans才会改变,才需要max对比当前和之前的长度,这个方法提交后执行效率都优于以下其他写法

   

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int start=0,ans=0;
        Map<Character,Integer> map=new HashMap<>();
        for(int i=0;i<s.length();i++){
            if(map.containsKey(s.charAt(i))&&start<=map.get(s.charAt(i))){
                start=map.get(s.charAt(i))+1;         
            }else{
                ans=Math.max(ans,i-start+1);
            }           
            map.put(s.charAt(i),i);            
        }
        return ans;
    }
}

写法二: start更新时直接用max计算

 

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int start=0,ans=0;
        Map<Character,Integer> map=new HashMap<>();
        for(int i=0;i<s.length();i++){
            if(map.containsKey(s.charAt(i))){
                start=Math.max(map.get(s.charAt(i))+1,start);              
                
            }
            ans=Math.max(ans,i-start+1);
            map.put(s.charAt(i),i);            
        }
        return ans;
    }
}

写法三:加边界条件

 

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n=s.length();
        if (n==0||n==1){
            return n;
        }
        int start=0,ans=0;
        Map<Character,Integer> map=new HashMap<>();
        for(int i=0;i<n;i++){
            if(map.containsKey(s.charAt(i))&&start<=map.get(s.charAt(i))){
                start=map.get(s.charAt(i))+1;         
            }else{
                ans=Math.max(ans,i-start+1);
            }           
            map.put(s.charAt(i),i);            
        }
        return ans;
    }
}

 Python

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        if len(s)=="":return 0
        if len(s)==1:return 1
        d_map = {}
        start = ans = 0
        for i in range(len(s)):
            if s[i] in d_map and start<=d_map[s[i]]:
                start = d_map[s[i]] + 1
            else:
                ans = max(ans, i - start + 1)
            d_map[s[i]] = i
        return ans

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        if len(s)=="":return 0
        if len(s)==1:return 1
        d_map = {}
        start = ans = 0
        for i in range(len(s)):
            if s[i] in d_map:
                start = max(d_map[s[i]] + 1,start)
            ans = max(ans, i - start + 1)
            d_map[s[i]] = i
        return ans

边界判断换成 for in 执行时间就边长了,虽然写法很python,但效率却不如显式直接判断 

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        n=len(s)
        if n in (0,1):
            return n
        d_map = {}
        start = ans = 0
        for i in range(n):
            if s[i] in d_map and start<=d_map[s[i]]:
                start = d_map[s[i]] + 1
            else:
                ans = max(ans, i - start + 1)
            d_map[s[i]] = i
        return ans

3、本题中语言点

  set 和第2第中用到的一样

4、就提交效率对比,显式条件判断,比调用函数执行效率高

        if len(s)=="":return 0
        if len(s)==1:return 1
   if n in (0,1):
            return n

            if(map.containsKey(s.charAt(i))&&start<=map.get(s.charAt(i))){
                start=map.get(s.charAt(i))+1;         
            }

 

            if(map.containsKey(s.charAt(i))){
                start=Math.max(map.get(s.charAt(i))+1,start);              
                
            }
  

后记:

后来突然想明白一个问题:这里的判断start<=map.get(s.charAt(i)) ,其实是使用map数据结构导致的影响。

单纯考虑到滑动窗口,只会想到窗口沿找index增大的方向往后滑动,但是当用map一直在存数据的时候,滑动窗口开始位置start之前的那些曾经放入map的元素并没有从map中删除过,一直存在map里面,所以有可能会start>map.get(s.charAt(i))。因为我们窗口要向后滑动,所以这里必须要加条件限制start<=map.get(s.charAt(i)) 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值