Day1—Hot100(5/100)

哈希

1.两数之和

在数组中找两数之和为目标值的数组下标。

  1. 暴力—— O ( n 2 ) O(n^2) O(n2),没有用到已知信息target
  2. 使用哈希表,利用target—— O ( n ) O(n) O(n)
    (1) 求当前数与target的差值,判断差值是否在dict中
    (2)是,则构成两数之和,返回
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        d = dict()

        for i, num in enumerate(nums):
            j = target - num
            if j in d:  # 判断差值是否在字典中
                return i,d[j]
            d[num] = i  # 如果不在则存储,避免重复值的影响

49.字母异位词分组

将str排序,保证不同词的异位词,对应的是同一个key

class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
        ans = []
        idx = 0
        d = dict()  # key:sort后的异位词, value:存储在第几个list
        for str in strs:
            s = ''.join(sorted(str))  # 把每个字符串按序排
            if s in d:
                ans[d[s]].append(str)
            else:
                d[s] = idx
                tmp = [str]
                ans.append(tmp)
                idx += 1
        return ans

128.最长连续序列(X)

方法1:
(1)set去重
(2)找每个连续序列的开头,即判断是否存在前一个元素

class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        s = set(nums)  # 去重
        ans = 0
        # 判断s中的每个数是否是连续序列的开头
        # 即,是否存在前一个数
        for i in s:
            if (i-1) not in s:
                tmp = 1 
                cur = i

                while (cur + 1) in s:
                    tmp += 1
                    cur += 1

                ans = max(ans, tmp)
        return ans

方法2:
(1)每次新进来哈希表一个数,判断当前数加入后,构成的连续序列的长度

class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        res = 0
        hash_dict = dict()
        for num in nums:
            # 新进来哈希表一个数
            if num not in hash_dict:
                # 获取当前数的最左边连续长度,没有的话就更新为0
                left = hash_dict.get(num-1,0)
                # 同理获取右边的数
                right = hash_dict.get(num+1,0)

                # 把当前数加入哈希表,代表当前数字出现过
                hash_dict[num] = 1
                # 更新长度
                length = left+1+right  # 左边长度+右边长度+当前位置1
                res = max(res,length)
                # 更新最左端点的值,如果left=n存在,那么证明当前数的前n个都存在哈希表中
                hash_dict[num-left] = length
                # 更新最右端点的值,如果right=n存在,那么证明当前数的后n个都存在哈希表中
                hash_dict[num+right] = length
                # 此时 【num-left,num-right】范围的值都连续存在哈希表中了
                # 即使left或者right=0都不影响结果
        return res

滑动窗口

3. 无重复字符的最长子串(X)

双指针滑动窗口,维护窗口[l, r],保证窗口内没有重复的元素
(1)控制右指针往右走,并通过哈希表快速查询是否出现重复元素
(2)如果出现重复元素,则控制左指针玩右走,从窗口中删除两个重复元素范围外的元素,同时删除左边的重复元素,保证新窗口无重复元素。

from collections import defaultdict
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        d = defaultdict(int)
        l,ans = 0,0
        
        for r in range(len(s)):
            d[ s[r] ] += 1
            
            if d[s[r]] > 1:  # 右指针的字符与窗口内字符出现重复
                while d[s[l]] == 1:  # 找到重复的字符
                    d[s[l]] = 0
                    l += 1
                    
                d[s[l]] -= 1  # 修改重复字符为不重复, 重新寻找下一个串
                l += 1
            
            ans = max(ans, r-l+1)
        
        return ans

438.找到字符串中所有字母异位词(X)

维护一个大小与p相等的窗口,判断窗口的字符数是否与目标一致
(1)官方题解:

class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        len_s, len_p = len(s), len(p)
        ans = []
        letter_s, letter_p = [0]*26, [0]*26

        if len_s < len_p:  # 不存在异位词
            return ans
        
        for i in range(len_p):
            letter_s[ord(s[i]) - 97] += 1
            letter_p[ord(p[i]) - 97] += 1
        
        if letter_s == letter_p:  # 判断前面len_p个是否相等
            ans.append(0)

        for i in range(len_s - len_p):  # 剩余长度小于len_p时,不需要继续
            # 把第i个元素移除窗口
            # 把 i + len_p 的元素加入窗口
            letter_s[ord(s[i])-97] -= 1
            letter_s[ord(s[i + len_p])-97] += 1

            if letter_s == letter_p:
                ans.append(i+1)
        
        return ans

(2)暴力(擦边过)

class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        len_s, len_p = len(s), len(p)
        p = "".join(sorted(p))
        ans = []

        if len_s < len_p:
            return ans

        for i in range(len_s - len_p + 1):
            if "".join(sorted(s[i:i+len_p])) == p:
                ans.append(i)
        return ans
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值