Python滑动窗口算法:求字符串最大无重复子串长度并输出子串

滑动窗口算法求最大无重复子串长度:

**

1.维护一个起始长度为0的窗口,窗口内都是没有重复的字符。
2.逐个遍历接收到的字符串,如果新遍历到的字符没有在窗口中出现过,那么窗口就“吃掉”这个字符,窗口右边界索引+1,左边界保持不变。
3.如果连续遍历到的字符都没有出现在窗口中,那么窗口将连续扩大。
4.如果遍历的字符在窗口中出现过,那么左窗口向右移动。
5.持续进行遍历,直到最后一个字符。
6.窗口只会扩大,不会缩小,每次记录窗口的最大值。

**

话不多说,来人,上代码!

方法一:逻辑难懂,复杂度高

def lengthoflongestsubstring(s):
    dic,maxln,start_index={},0,0
    all_str=[]
    for index,item in enumerate(s):
        if item in dic:     #如果窗口中存在当前字符,则左边界向右移动
            start_index=max(start_index,dic[item]+1)
        maxln=max(maxln,index-start_index+1)   #如果不存在,则扩大窗口
        windows=s[index +1- maxln:index+1]   #得到窗口中的子串
        all_str.append(windows)  #记录所有子串到列表
        dic[item] = index
    #print("所有子窗口为%s" %all_str)
    unexpect_str=[]
    for obj in all_str:
        for i in range(len(obj)):
            if obj.count(obj[i])!=1 or len(obj)<maxln:
                unexpect_str.append(obj)
    for j in unexpect_str:
        if j in all_str: 
            all_str.remove(j)
    final_result=set(all_str)
    print("最长无重复字符串为:%s" %final_result)
    print("最长无重复子串长度为:%s" %(maxln))
str=input('请输入字符串:').replace(' ','')    #去掉空格,空格会对结果有影响
lengthoflongestsubstring(str)

举例:输入字符串abcadaa:

运行结果:

请输入字符串:abcadaa
最长无重复字符串为:{'bcad'}
最长无重复子串长度为:4

整个过程:

举例:输入字符串:abcadaa
首先定义一个空字典:dic={},最大无重复子串长度maxln=0,字符起始位置start_index=0
使用enumerate函数,产生字符串“abcadaa”每个字符对应的index
每次循环都执行:dic[item] = index,更新字典key或给字典加入新的key
第一轮循环:item=a,a的index=0。因为dic为一个空字典,所以'a'不在dic里面,直接跳过if执行:maxln=max(maxln,index-start_index+1)语句
	那么:maxln=max(0,0-0+1=1,窗口长度为1
	第一轮循环结束的结果:maxln=1,start_index=0,dic={a:0}
	
第二轮循环:item=b,b的index=1,同样b不在dic里面:
	那么:maxln=max(1,1-0+1)=2,窗口长度为2
	第二轮循环结束的结果:maxln=1,start_index=0,dic={a:0,b:1}
	
第三轮循环:item=c,c的index=2,同样c不在dic里面:
	那么:maxln=max(2,2-0+1)=3,窗口长度为3
	第三轮循环结束的结果:maxln=3,start_index=0,dic={a:0,b:1,c:2}
	
第四轮循环:item=a,a的index=3,a在dic里面,进入if语句执行:start_index=max(start_index,dic[item]+1)
	那么:start_index=max(0,0+1)=1   这里的dic[item]为dic里面的值0,并不是当前a的index。窗口左边索引向右移动,从0位置到1位置
	maxln=max(3,3-1+1)=3,窗口长度不增加仍为3
	第四轮循环结束的结果:maxln=3,start_index=1,dic={a:3,b:1,c:2},a的key值更新了。
	
第五轮循环:item=d,d的index=4,同样d不在dic里面:
	那么:maxln=max(3,4-1+1)=4,窗口扩大为4
	第五轮循环结束的结果:maxln=4,start_index=1,dic={a:3,b:1,c:2,d:4}
	
第六轮循环:item=a,a的index=5,a在dic里面:进入if语句执行:start_index=max(start_index,dic[item]+1)
	那么:start_index=max(1,3+1)=4
	maxln=max(4,5-4+1)=4,窗口长度不变
	第六轮循环结束的结果:maxln=4,start_index=4,dic={a:5,b:1,c:2,d:4}
	
第七轮循环:item=a,a的index=6,a在dic里面:进入if语句执行:start_index=max(start_index,dic[item]+1)
	那么:start_index=max(4,5+1)=6
	maxln=max(4,6-6+1)=4,窗口长度不变
	第七轮循环结束的结果:maxln=4,start_index=6,dic={a:6,b:1,c:2,d:4}
	
循环结束,最终结果:
	maxln=4,start_index=6,dic={'a':6,'b':1,'c':2,'d':4}

至于求最长无重复子串:

在所有的窗口子串组成的列表中,删除掉有重复字符和长度小于最大无重复子串长度的子串,就可以得到了。

方法二复杂度低,逻辑易懂
附上力扣原题链接:
https://leetcode.cn/problems/longest-substring-without-repeating-characters/
题目只要求最长无重复子串长度,这里将最长无重复子串一并输出
逻辑:

定义初始为空的字符串,遍历题目给定字符串,如果该字符在初始字符串中出现过,那么将初始字符串切片为该字母第一次出现位置后面的片段,并维护一个最长的长度;如果该字符未在初始字符串中出现,那么直接初始字符串直接追加该字符。维护最长的初始字符串,就得到了最长子串和最长子串长度

代码:

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        if not s:
            return 0
        else:
            zichuan = ""
            max_len = 0
            for i in s:
                if i in zichuan:
                    if len(zichuan) > max_len:
                        max_len =len(zichuan)     #得到最长子串长度
                        max_zichuan = zichuan    #得到最长子串
                    index = zichuan.index(i)
                    zichuan = zichuan[index+1:]
                    zichuan += i
                else:
                    zichuan += i
            return  max(max_len,len(zichuan)),max_zichuan
a = Solution()
print(a.lengthOfLongestSubstring("pwwkew"))
输出最长子串长度以及最长无重复子串:

E:\pycharm_project\venv\Scripts\python.exe E:/pycharm_project/venv/2.py
(3, 'wke')

力扣通过率:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值