Leetcode Hot 100 刷题记录,python语言

128 最长连续序列

参考https://leetcode.cn/problems/longest-consecutive-sequence/solutions/276931/zui-chang-lian-xu-xu-lie-by-leetcode-solution

class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        longest_streak = 0
        nums_set = set(nums)

        for num in nums_set:
            if num-1 not in nums_set:
                current_num = num
                current_streak = 1
                while current_num + 1 in nums_set:
                    current_num += 1
                    current_streak += 1
                longest_streak = max(longest_streak, current_streak)

        return longest_streak

438 找到字符串中所有字母异位词

这段代码是用来解决 LeetCode 上的 “Find All Anagrams in a String” 问题,目的是找出字符串 s 中所有与字符串 p 是字母异位词的子串的起始索引。下面是对代码中各部分的解释:

变量说明:

s_len:字符串 s 的长度。
p_len:字符串 p 的长度。
ans:存放结果,即符合条件的起始索引。
s_count 和 p_count:分别是长度为 26 的数组,用来记录字符串中各个字符的出现次数。这里假设只考虑小写字母,因此数组长度为 26。s_count 记录当前窗口(或子串)中字符的出现次数,p_count 则记录模式串 p 中字符的出现次数。
初始化计数器:

遍历模式串 p 的前 p_len 个字符,更新 s_count 和 p_count。
s_count[ord(s[i]) - 97] += 1:将字符串 s 中当前字符的计数加一。ord(s[i]) - 97 的部分将字符映射到 s_count 数组的索引,即 ‘a’ 对应索引 0,‘b’ 对应索引 1,…,‘z’ 对应索引 25。
p_count[ord(p[i]) - 97] += 1:将模式串 p 中当前字符的计数加一。
初始比较:

如果初始时 s_count 等于 p_count,则说明从 s 的起始位置开始的长度为 p_len 的子串是 p 的字母异位词,将起始索引 0 加入 ans 中。
滑动窗口过程:

从索引 0 开始到 s_len - p_len 结束,依次滑动窗口。
每次滑动窗口时,更新 s_count:
s_count[ord(s[i]) - 97] -= 1:将窗口左边界字符在 s_count 中的计数减一。
s_count[ord(s[i + p_len]) - 97] += 1:将窗口右边界字符在 s_count 中的计数加一。
每次更新窗口后,比较 s_count 是否等于 p_count,如果相等,则将当前窗口的起始索引 i + 1 加入 ans 中。
返回结果:

返回 ans,其中存储了所有符合条件的起始索引。
这种方法的时间复杂度为 O(n),其中 n 是字符串 s 的长度。主要的计算量在于遍历字符串和更新计数器,而每次更新计数器都是常数时间操作。

class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        s_len, p_len = len(s), len(p)
        
        if s_len < p_len:
            return []

        ans = []
        s_count = [0] * 26
        p_count = [0] * 26
        for i in range(p_len):
            s_count[ord(s[i]) - 97] += 1 #ord('a') = 97, b 98, c 99
            p_count[ord(p[i]) - 97] += 1 

        if s_count == p_count:
            ans.append(0)

        for i in range(s_len - p_len): # s_count还保留着初始窗口的字母统计次数;滑动窗口的左边界,循环;每滑动一次,只减去开头,增加结尾的字符,中间不动,所以,没有i到i+p_len中间的字符次数变化
            s_count[ord(s[i]) - 97] -= 1
            s_count[ord(s[i + p_len]) - 97] += 1 # 滑动窗口的右边界
            
            if s_count == p_count:
                ans.append(i + 1)

        return ans

560 和为K的子数组

变量说明:
nums:输入的整数数组。
k:目标和。
count:符合条件的子数组个数,即和为 k 的连续子数组个数。
sum:当前累积的子数组和。
sumDict:字典,用来记录累积和出现的次数。键为累积和的值,值为该累积和出现的次数。初始时,将 {0: 1} 放入字典中,表示累积和为 0 的情况出现了 1 次。
解题思路:
初始化:

count 初始化为 0,用于计数符合条件的子数组个数。
sum 初始化为 0,用于累积当前子数组的和。
sumDict 初始化为 {0: 1},表示累积和为 0 的情况出现了 1 次。
遍历数组 nums:

每次遍历到数组中的一个数 num,将其加到 sum 中,表示当前累积的子数组和。
判断 sum - k 是否在 sumDict 中:
如果 sum - k 存在于 sumDict 中,说明之前有子数组的累积和为 sum - k,此时 sum - (sum - k) = k,即找到了一个符合条件的子数组,将 count 加上 sumDict[sum - k],表示有多少个以前累积和为 sum - k 的子数组,现在都可以形成一个新的符合条件的子数组。
更新 sumDict:
将 sum 加入 sumDict 中,如果 sum 已经在 sumDict 中,将其对应的值加 1;否则,将 sum 加入 sumDict,并将其值设为 1。
返回结果:

遍历完整个数组后,count 中存储的就是所有和为 k 的连续子数组的个数,将其作为结果返回。
时间复杂度分析:
该算法只需要遍历数组一次,每次操作都是常数时间复杂度,因此总体时间复杂度为 O(n),其中 n 是数组 nums 的长度。
空间复杂度主要取决于 sumDict 的大小,最坏情况下 sumDict 可能包含 n 个不同的累积和,因此空间复杂度为 O(n)。
这种方法利用了累积和的性质,通过哈希表记录累积和出现的次数,从而有效地解决了该问题。

class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        if not nums:
            return 0
        count = 0 # 有多少个满足条件的连续子数组
        sum = 0 # 当前累计的子数组的和
        sumDict = {0: 1} # 哈希表 ;用来记录累积和出现的次数。
        # 键为累积和的值,值为该累积和出现的次数。
        # 初始时,将 {0: 1} 放入字典中,表示累积和为 0 的情况出现了 1 次。
        for num in nums: # 比如以nums = [1,1,1], k = 2为例子,
        #第一次循环sum=1,加入字典{1:1},
        #第二次sum=2,sum-k=0,在字典中,count=0+1.同时sum=2加入字典,{2:1}
        #第三次sum=3,sum-k=3-2=1在字典中{1:1},就是说,在前面某个位置到开头的累计和为1,那么从那个位置到当前num的累计和为sum - (sum-k) = k,为目标和k。所以count加上,那个位置对应的次数,比如有多个那个位置
            sum += num # 当前子数组的和,累计
            if sum - k in sumDict: 
                count += sumDict[sum - k]
            if sum in sumDict:
                sumDict[sum] += 1 
            else:
                sumDict[sum] = 1
        return count

238 除自身以外数组

这段代码是用来计算除自身以外数组元素的乘积的,使用了两个阶段的累积乘积计算方法,分别是下三角和上三角的概念。

让我们逐步解释这段代码:

初始化变量:

ans 是一个长度为 len(nums) 的列表,初始化为全1。它最终会存储每个元素左侧所有元素的乘积。
tmp 是一个临时变量,用于存储右侧所有元素的乘积的累积值,初始为1。
计算下三角(左侧乘积):

第一个 for 循环从 1 到 len(nums)-1,计算 ans[i],表示 nums[i] 左侧所有元素的乘积。具体计算为 ans[i] = ans[i - 1] * nums[i - 1]。
这个循环完成后,ans[i] 存储的是 nums[i] 左侧所有元素的乘积。
计算上三角(右侧乘积):

第二个 for 循环从 len(nums)-2 到 0,逆序计算每个元素 nums[i] 右侧所有元素的乘积。
在循环中,tmp 乘以 nums[i + 1],然后 ans[i] 乘以 tmp。这样可以得到 nums[i] 左侧和右侧所有元素的乘积。
这一步完成后,ans[i] 存储的是除 nums[i] 外所有元素的乘积。
返回结果:

最后返回 ans 列表,其中 ans[i] 存储的是除 nums[i] 外所有元素的乘积。
这种方法避免了使用除法操作,通过两个阶段的累积乘积计算来实现目标,时间复杂度为 O(n),空间复杂度为 O(1),符合题目要求。

class Solution:
    def productExceptSelf(self, nums: List[int]) -> List[int]:
        res = [1]*len(nums)
        tmp = 1
        for i in range(1, len(nums)):
            res[i] = res[i-1] * nums[i-1] # 下三角,存储每个元素左侧所有元素的乘积。
        for i in range(len(nums)-2, -1, -1):
            tmp *= nums[i+1] # 上三角,存储每个元素右侧所有元素的乘积。
            res[i] *= tmp
        return res       
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值