LeeCode算法题

本文概述了几道LeetCode题目,涉及哈希、双指针、滑动窗口等技巧,包括两数之和、字母异位词分组、最长连续序列、移动零、盛水最多容器、三数之和、接雨水、无重复字符子串、和为k子数组、滑动窗口最大值等,展示了如何用这些技术解决常见编程挑战。
摘要由CSDN通过智能技术生成

哈希

两数之和(https://leetcode.cn/problems/two-sum/?envType=study-plan-v2&envId=top-100-liked)
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        idx = {}
        for i,d in enumerate(nums):
            if target - d in idx:
                return [i,idx[target - d]]
            idx[d] = i
字母异位词分组(https://leetcode.cn/problems/group-anagrams/?envType=study-plan-v2&envId=top-100-liked)
# 哈希表,键是排序的字母组,值是列表
class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
        idx = {}
        for s in strs:
            sortedString = ''.join(sorted(s))
            if sortedString in idx:
                idx[sortedString].append(s)
            else:
                idx[sortedString] = [s]
        
        return list(idx.values())
最长连续序列(https://leetcode.cn/problems/longest-consecutive-sequence/?envType=study-plan-v2&envId=top-100-liked)
# 遍历一次存哈希表先,然后找开头,找到开头开始+1在哈希表里找
class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        xcount = 0
        numSet = set(nums)
        for n in numSet:
            count = 1
            if n - 1 not in numSet:
                while n + 1 in numSet:
                    count += 1
                    n += 1
            if count > xcount:
                xcount = count

        return xcount

双指针

移动零(https://leetcode.cn/problems/move-zeroes/?envType=study-plan-v2&envId=top-100-liked)
# 使用双指针,交换的做法
class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        j = 0
        for i in range(len(nums)):
            if nums[i]:
                nums[i],nums[j] = nums[j],nums[i]
                j += 1
        return nums
盛水最多的容器(https://leetcode.cn/problems/container-with-most-water/?envType=study-plan-v2&envId=top-100-liked)
class Solution:
    def maxArea(self, height: List[int]) -> int:
        i,j,maxWater = 0,len(height)-1,0
        while j > i:
            if height[i] > height[j]:
                maxWater = max(maxWater,height[j]*(j-i))
                j -= 1
            else:
                maxWater = max(maxWater,height[i]*(j-i))
                i += 1
        return maxWater
三数之和(https://leetcode.cn/problems/3sum/?envType=study-plan-v2&envId=top-100-liked)
class Solution:
    def threeSum(self, nums):
        nums = sorted(nums)
        res = []
        for k in range(len(nums)-2):
            if nums[k] > 0:break
            if k > 0 and nums[k] == nums[k-1]:continue
            i,j = k + 1,len(nums)-1
            while j > i:
                addResult = nums[k] + nums[i] + nums[j]
                if addResult == 0:
                    res.append([nums[k],nums[i],nums[j]])
                    while j > i and nums[i] == nums[i + 1]: i += 1
                    while j > i and nums[j] == nums[j - 1]: j -= 1
                    i += 1
                    j -= 1
                elif addResult > 0:
                    j -= 1
                else:
                    i += 1    
        return res
接雨水(https://leetcode.cn/problems/trapping-rain-water/?envType=study-plan-v2&envId=top-100-liked)
# 我一开始的想法:一层一层算积水,从第一层开始逐步增加层数计算积水量
# class Solution:
#     def trap(self, height):
#         i, j, floor, res = 0, len(height) - 1, 1, 0
#         while i < j - 1:
#             while height[i] < floor:
#                 i += 1
#                 if i > len(height) - 2 :
#                     break
#             while height[j] < floor:
#                 j -= 1
#                 if j < 2:
#                     break
#             if i > j - 1 :
#                 break

#             # print(j, "j++")
#             # print(i, "i++")
#             res += j - i - 1
#             for k in range(i + 1, j):
#                 if height[k] >= floor:
#                     res -= 1
#             # print(res, "res++")

#             floor += 1
#         return res


# 可以看BILIBILI帮助理解https://www.bilibili.com/video/BV1Qg411q7ia/?spm_id_from=333.337.search-card.all.click&vd_source=e8c4fa6e99b7896ec2ef4f1bb7bed7ce
# 动态规划,官方题解的理解
# class Solution:
#     def trap(self, height):
#         l2r,r2l,maxl2r,maxr2l,res = [],[],0,0,0
#         for h in height:
#             if h > maxl2r:
#                 maxl2r = h
#             l2r.append(maxl2r)
#         for h in reversed(height):
#             if h > maxr2l:
#                 maxr2l = h
#             r2l.insert(0,maxr2l)
#         # for index, h in enumerate(height):
#         #     if l2r[index] > r2l[index]:
#         #         if h < r2l[index]:
#         #             res += r2l[index] - h
#         #     else:
#         #         if h < l2r[index]:
#         #             res += l2r[index] - h
#         for l,r,h in zip(l2r,r2l,height):
#             res += min(l,r) - h
#         print(res,"res++")
#         return res

# 双指针实现,同样可以通过上面的视频帮助理解,关于我应该怎么想到这种做法,双指针好像经常用于在数组中比较大小?
class Solution:
    def trap(self, height):
        i,j,maxl,maxr,res = 0,len(height)-1,0,0,0

        while i <= j:
            maxl = max(height[i],maxl)
            maxr = max(height[j],maxr)
            if maxl < maxr:
                res += maxl - height[i]
                i += 1
            else:
                res += maxr - height[j]
                j -= 1
        return res

滑动窗口

无重复字符的最长子串
# 第一次做法(没过要求的时间)
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        maxL,res,_dict = 0,0,{}
        for index,value in enumerate(s):
            for ss in s[index:]:
                print(ss,"ss++")
                print(_dict,"dict++")
                if not _dict.get(ss,0):
                    _dict[ss] = 1
                    maxL += 1
                    if maxL > res:
                        res = maxL
                else:
                    _dict,maxL = {},0
                    break
        return res
# 我的思路:找规律,省去不必要的滑动窗口的尝试(过要求的时间)
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        maxL,res,_dict,i = 0,0,{},0
        while i <= len(s) - 1:
            # print(i,"i++")
            # print(s[i],"s[i]++")
            # print(_dict,"_dict++")
            if _dict.get(s[i],"00") == "00":
                _dict[s[i]] = i
                maxL += 1
                if maxL > res:
                    res = maxL
                i += 1
            else:
                i = _dict[s[i]] + 1
                maxL = 0
                _dict = {}
        print(res)
        return res

# 网上解法,尝试,关于滑动窗口有模板总结,可以看https://leetcode.cn/problems/longest-substring-without-repeating-characters/solutions/876061/yi-ge-mo-ban-miao-sha-10dao-zhong-deng-n-sb0x/?envType=study-plan-v2&envId=top-100-liked
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        _list,res = [],0
        for ss in s:
            while ss in _list:
                _list.pop(0)
            _list.append(ss)
            res = max(len(_list),res)
        return res
找到字符串中所有字母异位词(https://leetcode.cn/problems/find-all-anagrams-in-a-string/)
# 我想出来的解,能过提交,但不是最优解
class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        huadong,res,_p = [],[],''.join(sorted(p))
        xianzhiLen = len(p)
        for index,ss in enumerate(s):
            huadong.append(ss)
            if len(huadong) == xianzhiLen:
                _ = sorted(huadong)
                if "".join(_) == _p:
                    res.append(index-xianzhiLen+1)
                huadong.pop(0)

        print(res)
        return res

子串

和为k的子数组(https://leetcode.cn/problems/subarray-sum-equals-k/submissions/?envType=study-plan-v2&envId=top-100-liked)
# 我第一次提交的暴力破解,没过时间限制
class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        res = 0
        for index,value in enumerate(nums):
            _ = 0
            for i in nums[index:]:
                # print(i,"i++")
                # print(_,"_++")
                _ += i
                if _ == k:
                    res += 1


        print(res)
        return res


# 使用前缀和(这个视频帮助理解https://www.bilibili.com/video/BV1gN411E7Zx/)
class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        res,_dict,sumN = 0,{},0
        for n in nums:
            sumN += n
            # 这里我做了优化,视频里是建议直接在哈希表初始化的时候加0:1这个键值对,但是我认为这种做法不对,这样会导致当需要前缀和为0的时候多计数
            # 所以我用下面这种方法做
            if sumN - k == 0:
                res += 1
            if sumN - k in _dict:
                res += _dict[sumN - k]
            _dict[sumN] = _dict.get(sumN,0) + 1
        # print(res)
        return res
滑动窗口最大值(https://leetcode.cn/problems/sliding-window-maximum/description/?envType=study-plan-v2&envId=top-100-liked)
# 这个视频帮助很大:https://www.bilibili.com/video/BV1bM411X72E/
# 找出重复的步骤,抽象出情况

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        d,res = deque(),[]

        for i,v in enumerate(nums):

            # 进!
            while d and nums[d[-1]] < v:
                d.pop()
            d.append(i)
            # 出!
            if i - d[0] >= k:
                d.popleft()

            # 记录!
            if i >= k - 1:
                res.append(nums[d[0]])
        # print(res)
        return res


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值