小白的LeetCode刷题日记3--python3

LeetCode第3题:无重复字符的最长子串

题目描述:

在这里插入图片描述

要求:

在这里插入图片描述

第一种解法:遍历对比

这题我首先想到的就是对比,即将之前已经遍历过的元素加入列表中,利用python的in操作符,可以简单地进行对比,所以我们先建立一个store列表用来存储已遍历过的元素,用maxlen来记录最长字串长度,用tmplen来记录遍历过程字串长度的变化。这题用python能使代码更简洁,写起来也方便

store = []
maxlen = 0
tmplen = 0

武器有了,接下来开始实践,首先一个for循环取字符串s的字符

for i in s:

接下来开始if判断,如果当前的i元素已经存在于列表store,首先判断最长字串长度maxlen是否更新,如果临时记录字串长度的tmplen已经比maxlen长,则更新,相等和小于皆不更新

if i in store:
	if maxlen < tmplen:
		maxlen = tmplen

然后就是用index索引函数寻找当前在列表store中和i元素相同的下标,利用列表的切片功能将其后面的元素切出来赋予store(因为在store中和i相同的元素后面可能还有元素存在,所以需要用到切片),然后再将当前的i元素用append函数加入,再求一下当前列表长度即可

store = store[store.index(i)+1:]
store.append(i)
tmplen = len(store)

如果当前i元素不在列表store里面,则说明字串加上i元素后仍没有重复元素,此时tmplen需要加1,store列表再添加当前元素即可

else:
	tmplen += 1
	store.append(i)

最后还需要判断maxlen和tmplen之间的长度,因为上面的for循环在最后一个元素判断完后,若仍是新元素,则maxlen没有得到更新,所以最后要补一个更新,再返回maxlen即可完成

if maxlen < tmplen:
	maxlen = tmplen
return maxlen

完整代码如下:

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        store = []
        maxlen = 0
        tmplen = 0
        for i in s:
            if i in store:
                if maxlen < tmplen:
                    maxlen = tmplen
                store = store[store.index(i)+1:]
                store.append(i)
                tmplen = len(store)
            else:
                tmplen += 1
                store.append(i)
        if maxlen < tmplen:
            maxlen = tmplen
        return maxlen
复杂度分析

时间复杂度:这里我们只有一个for循环来对字符串进行遍历,for里面的语句在字符串长度为N时可以省略,因此时间复杂度为O(N)

空间复杂度:空间复杂度取决于我们所建立的store列表长度,最长的情况就是整个字符串都没有重复,因此空间复杂度也为O(N)?实际上我们的字符集是有长度限制的,以ascii码为例,一共就128个,因此空间复杂度最多也就O(128),官方用字母∣Σ∣表示,所以空间复杂度为O(∣Σ∣)

优缺

在这里插入图片描述
这个暂时还没想到。

第二种解法:滑动窗口

这种是LeetCode官方解法,代码更加简洁。解法用到了集合set()来记录,集合和字典一样,底层都是哈希表实现的,具体是将集合当作一个滑动可变长窗口,利用左i、右rk两个指针移动,当右指针移动时进行判断,若当前元素s[rk+1]不在集合里,就将其加入集合中,并且右指针rk+1,即右移一个元素,当元素在集合时,就会跳出while循环,并记录当前字串长度,然后进入下一个for循环,因为跳出for循环说明右指针指向的元素和左指针指向相同,因此就需要将左指针指向的元素删除
代码解析:

occ = set() #集合,充当滑动窗口
n = len(s)  #for循环需要遍历的长度即是字符串s的长度
rk, ans = -1, 0 #rk是右指针(初始-1即还没开始移动,因为字符串初始下标为0),ans则是记录最长字串长度
for i in range(n):
    if i != 0:
        occ.remove(s[i - 1])

利用for循环的i来充当左指针的移动,当进行for循环且不为0是,必是因为出现相同的元素或者已经没有相同元素,拿到正确答案了

while rk + 1 < n and s[rk + 1] not in occ:
    occ.add(s[rk + 1])
    rk += 1

利用右指针右移,在每次右移过程中都会进行判断当前元素是否已经存在集合,没有添加当前元素,并右移(即rk+=1)

ans = max(ans, rk - i + 1)

这里就是ans最长字串长度的更新,当新的字串长度rk-i+1大时,就更新,没有就保持原值,最后return ans就行了
完整代码如下:

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        occ = set()
        n = len(s)
        rk, ans = -1, 0
        for i in range(n):
            if i != 0:
                occ.remove(s[i - 1])
            while rk + 1 < n and s[rk + 1] not in occ:
                occ.add(s[rk + 1])
                rk += 1
            ans = max(ans, rk - i + 1)
        return ans
复杂度分析

时间复杂度:官方是说O(N),其中 N是字符串的长度。左指针和右指针分别会遍历整个字符串一次。因为最坏情况是O(∣Σ∣N),即当字符串长度为N,且是按照字符最大不重复长度的∣Σ∣循环组成的,首次遍历后,接下来每次for循环都要左右指针各移动一次,一共N次,当N无限大时,因为∣Σ∣是常数,因此省略,所以时间复杂度为O(N)
空间复杂度:为字符最大不重复的长度,即O(∣Σ∣)

优缺

在这里插入图片描述
运算结果相比解法1慢了一些,因此我觉得在字符串长度小的时候用第一种方法好一些,少了左指针的移动,因为解法1是直接切片,而不是一个一个移动的。在字符串很长时则解法1、2没有差别

运算时间可能会因本人电脑性能原因有差,这里仅供参考,具体以个人电脑运行为主
图均参考LeetCode

若有出错,请大家多批评指正!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python LeetCode刷题指南是一个帮助想要提高他们算法和编程能力的人通过LeetCode平台进行刷题的指南。以下是一些建议和步骤: 1. 建立良好的编程基础:在开始之前,确保你对Python编程语言有一定的了解,并掌握基本的数据结构和算法知识,比如链表、栈、队列、二叉树等。 2. 熟悉LeetCode题库:花一些时间浏览LeetCode题库,了解不同题目的分类和难度等级。这样你就能更好地规划你的刷题计划。 3. 制定计划和目标:根据你自己的时间和目标,设置一个刷题计划。计划可以包括每天刷多少题目、每周完成的目标等。通过制定计划,你可以更有条理地刷题,并逐渐提高自己的能力。 4. 解题思路和算法:在开始解题之前,先仔细阅读题目,理解题意和要求。然后,考虑适合该问题的算法和数据结构。在LeetCode网站上,每个问题都有详细的解题思路和讨论,可以从中获得灵感。 5. 编码和调试:根据你选择的算法和数据结构,使用Python编写解决方案。在编码过程中,注重代码的可读性和可维护性。完成后,运行代码进行测试并调试。 6. 提交和优化:在完成一个问题的解答后,提交你的解答并查看运行结果。如果通过所有的测试用例,那么恭喜你!如果没有通过,仔细检查代码并修改错误。同时,尝试优化你的解法,使其更高效。 7. 学习和总结:刷题是一个学习和成长的过程。通过刷题,你会遇到不同的问题和挑战,学会更多的算法和技巧。每个完成的题目都对你的编程能力有所增加,不论是通过自己的思考还是学习他人的解法。完成一个问题后,不要忘记总结并思考这个问题的解题思路和优化方法。 总之,Python LeetCode刷题指南提醒我们刷题不仅仅是为了解决具体问题,更是为了提升我们的算法和编程能力。通过系统化的刷题计划和总结,我们可以逐渐掌握更多的算法和数据结构,并在实际项目中得以应用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值