哈希
两数之和(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