力扣hot100----1day

1.两数之和

解法:

复制代码
class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        num_map={}
        for i,num in enumerate(nums):
            a=target-num
            if a in num_map:
                return (num_map[a],i)
            num_map[num]=i

1.定义一个字典,用来接收已经遍历的值和对应的下标

2.用target减去当前遍历的值,判断结果是否在字典里,若存在,返回二者下标,如不存在,将该值以及下标存进字典里

enumerate 是 Python 内置函数,用于同时获取可迭代对象(如列表、元组、字符串等)的元素及其对应的索引(下标)

2.字母异位词分组

解法:

复制代码
class Solution(object):
    def groupAnagrams(self, strs):
        """
        :type strs: List[str]
        :rtype: List[List[str]]
        """
        anagram_map={}
        for str in strs:
            sorted_s="".join(sorted(str))
            if sorted_s in anagram_map:
                anagram_map[sorted_s].append(str)
            else:
                anagram_map[sorted_s]=[str]
        return list(anagram_map.values())

思路:

1.因为异位词的每个字母和数量是相同的,那么将每个词的字母进行排序,那么这个所有的异位词就一样了

2.使用字典,将异位词排序后的字符串作为key,然后将排序后的词添加到对应的列表中

3.最后将字典的值导出,转化为列表,返回结果

语法:

sorted(s) : Python 内置函数,对字符串 s 中的字符进行排序,返回一个排序后的字符列表。例如:s = "eat" 时,sorted(s) 会返回 ['a', 'e', 't'](按字母顺序排序)。

''.join(...): 字符串的 join 方法,将一个可迭代对象(这里是排序后的字符列表)拼接成一个字符串。

例如:''.join(['a', 'e', 't']) 会返回 "aet",作为字典的键。

anagram_map.values(): 字典的 values 方法,返回一个包含所有值的视图(这里每个值都是一个字母异位词分组的列表)。

3.最长连续序列

复制代码
class Solution(object):
    def longestConsecutive(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        nums_set=set(nums)
        longest=0
        for num in nums_set:
            cur_len=1
            cur_num=num
            if num-1 not in nums_set:
                while cur_num+1 in nums_set:
                    cur_len+=1
                    cur_num+=1
            longest=max(longest,cur_len)
        return longest        

思路:

1.利用set集合去掉重复的数

2.利用set集合查找元素的时间复杂度较低

3.查找每段连续的数的开始位置,如果num-1存在于set集合中,那么他就不是这一段数中最开始的数

4.找到最开始的数后,循环判断后面的是否在集合里面,如果在就更新长度,如果不在,就用统计的长度和最长值进行比较

5.返回最大值

4.移动零

复制代码
class Solution(object):
    def moveZeroes(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        left=right=0
        n=len(nums)
        while right<n:
            if nums[right]!=0:
                nums[left],nums[right]=nums[right],nums[left]
                left+=1
            right+=1

思路:

1.使用双指针

2.使用right向后遍历,遇到不是0的数就和left位置交换

3.每次交换完,left++

4.每次遍历一个数,right++

5.相当于以left为界,left左边的数是非0数,left右边的数是0,right向后遍历未处理的数,遇到非0数,就将其放到left左边

5.盛最多水的容器

复制代码
class Solution(object):
    def maxArea(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        l,r=0,len(height)-1
        maxArea=0
        while l<r:
            area=min(height[l],height[r])*(r-l)
            maxArea=max(area,maxArea)
            if height[l]<=height[r]:
                l+=1
            else:
                r-=1
        return maxArea

思路:

1.从容器的两边向内寻找最大容器,此时容器的底是最大的

2.每次改变一边,哪一边短就向内靠拢,寻找最大容器

3.left++,right--,为了寻找最大的容器,如果不是短板移动,那么底不断变小,但高始终取决于短板,那么他的容器大小始终不会变高

6.三数之和

复制代码
class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        n=len(nums)
        nums.sort()
        res=[]
        for i in range(n):
            if nums[i]>0:
                break
            if nums[i]==nums[i-1] and i>0:
                continue

            l,r=i+1,n-1
            while l<r:
                total=nums[l]+nums[r]
                if -nums[i]>total:
                    l+=1
                elif -nums[i]<total:
                    r-=1
                else:
                    res.append([nums[i],nums[l],nums[r]])
                    while l<r and nums[l]==nums[l+1]:
                        l+=1
                    while l<r and nums[r]==nums[r-1] :
                        r-=1
                    l+=1
                    r-=1
        return res

思路:

1.对列表排序,方便去重

2.遍历列表,出现重复的数跳过

3.获取到遍历的元素的相反数,在其右边区间使用双指针,求和和相反数进行比较,大于相反数,right--,小于相反数,left++

4.等于相反数,循环查找下一对等于相反数的组合,遇到相同的数,跳过

5.返回列表

7.接雨水

复制代码
class Solution(object):
    def trap(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        if not height:
            return 0
        n=len(height)-1
        res=0
        left_max=height[0]
        right_max=height[n]
        l,r=0,n
        while l<r:
            if height[l]<height[r]:
                if height[l]<left_max:
                    res+=left_max-height[l]
                else:
                    left_max=height[l]
                l+=1
            else:
                if height[r]<right_max:
                    res+=right_max-height[r]
                else:
                    right_max=height[r]
                r-=1
        return res   

1. 核心逻辑:单个柱子的接水量

对于任意一个柱子,它能接住的雨水量 = min(左侧最高柱高度, 右侧最高柱高度) - 自身高度(若结果为正,则该值为接水量;若为负,接水量为 0)。

比如示例中某个高度为0的柱子,其左侧最高柱是2,右侧最高柱是3,那么它能接的水量就是min(2, 3) - 0 = 2

2. 双指针法的合理性

我们用两个指针left(从左往右)和right(从右往左)遍历数组,同时维护left_maxleft左侧的最高柱高度)和right_maxright右侧的最高柱高度)。

  • height[left] < height[right]时:因为right右侧存在比height[left]更高的柱(否则height[right]不会更大),所以left位置的 ** 左侧最高柱left_max** 就是它的 "左边界",此时可直接用left_max - height[left]计算接水量(或更新left_max)。

  • height[left] >= height[right]时:同理,right位置的 ** 右侧最高柱right_max** 就是它的 "右边界",此时可直接用right_max - height[right]计算接水量(或更新right_max)。

这种方式确保了每个柱子仅被遍历一次,同时准确利用了 "左右最高柱的较矮者" 这一核心逻辑,从而高效解决问题。

8.无重复字符的最长子串

复制代码
class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        char_map={}
        left=0
        max_len=0

        for right in range(len(s)):
            if s[right] in char_map and char_map[s[right]]>=left:
                left=char_map[s[right]]+1
            char_map[s[right]]=right
            max_len=max(max_len,right-left+1)
        return max_len

思路:

1.利用滑动窗口

利用right指针向右遍历,将遍历的字符和下标存入字典中

2.当right向右遍历的过程中,判断当前字符是否存在于字典中,并且上一次索引在left之后,那么这个字符就在窗口中,就将left指向上一次出现索引的后一位,并计算当前无重复字符串的最大长度

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

复制代码
class Solution(object):
    def findAnagrams(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: List[int]
        """
        s_len=len(s)
        p_len=len(p)
        if p_len>s_len:
            return []
        s_count=[0]*26
        p_count=[0]*26
        ans=[]
        for i in range(p_len):
            s_count[ord(s[i])-97]+=1
            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[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

思路:

1.使用滑动窗口

2。利用数组统计每个字符出现的次数,也统计s字符串相同长度下,每个字符出现的次数

每次将窗口向后移动一格,判断两个维护的数组是否相等,若相等,则找到一个异位词

复制代码
class Solution(object):
    def findAnagrams(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: List[int]
        """
        s_len,p_len=len(s),len(p)
        if p_len>s_len:
            return []

        count=[0]*26
        ans=[]
        len1=s_len-p_len
        for i in range(p_len):
            count[ord(s[i])-97]+=1
            count[ord(p[i])-97]-=1
        differ=[c!=0 for c in count].count(True)
        if differ==0:
            ans.append(0)
        
        for j in range(s_len-p_len):
            if count[ord(s[j])-97]==1:
                differ-=1
            elif count[ord(s[j])-97]==0:
                differ+=1
            count[ord(s[j])-97]-=1

            if count[ord(s[j+p_len])-97]==-1:
                differ-=1
            elif count[ord(s[j+p_len])-97]==0:
                differ+=1
            count[ord(s[j+p_len])-97]+=1
            if differ==0:
                ans.append(j+1)
        return ans

10.和为k的子数组

复制代码
class Solution(object):
    def subarraySum(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        count=0
        sum_map=defaultdict(int)
        pre_sum=0
        sum_map[0]=1
        for num in nums:
            pre_sum+=num
            if pre_sum-k in sum_map:
                count+=sum_map[pre_sum-k]
            sum_map[pre_sum]+=1
        return count

思路

利用前缀和和hash表

1.因为子数组是连续的,我们使用前缀和,就可以获取到中间某段数组的和

2.中间某段数组的和我们希望是目标值k,而目标值k是确定的,所以我们需要看后一段前缀和减去k的值,在前面的前缀和中出现了几次,则找到几个前缀和数组

3.前缀和出现的次数我们使用hash表来存储

语法

在遍历数组时,我们需要频繁查询哈希表中是否存在某个前缀和(即 preSum - k)。如果使用普通字典(如 dict),当查询的键不存在时会抛出 KeyError,需要手动判断或捕获异常。

defaultdict可以指定一个默认值类型(这里用 int),当查询的键不存在时,会自动返回该类型的默认值(int 的默认值是 0)。

细节

初始化时,将sum_map[0]=1,当我们刚开始遍历第一个元素时,map里面为空,而如果第一个元素就为目标值时,前缀和里面找不到和为0的数组,但其实,他一个元素就能构成目标子数组,初始化的目的是为了防止一个元素构成目标子数组的情况

相关推荐
2501_941236212 小时前
使用PyTorch构建你的第一个神经网络
jvm·数据库·python
程序猿_极客2 小时前
【2025 最新】 Python 安装教程 以及 Pycharm 安装教程(超详细图文指南,附常见问题解决)
开发语言·python·pycharm·python安装以及配置
2501_941235732 小时前
C++中的装饰器模式变体
开发语言·c++·算法
2501_941111252 小时前
基于C++的爬虫框架
开发语言·c++·算法
小欣加油2 小时前
leetcode 429 N叉树的层序遍历
数据结构·c++·算法·leetcode·职场和发展
b***66612 小时前
Python 爬虫实战案例 - 获取社交平台事件热度并进行影响分析
开发语言·爬虫·python
民乐团扒谱机2 小时前
【元启发算法】SMA黏菌算法:当自然智慧走进代码世界
算法
chushiyunen2 小时前
django使用笔记
笔记·python·django
Kuo-Teng2 小时前
LeetCode 142: Linked List Cycle II
java·算法·leetcode·链表·职场和发展