冲冲冲!!! 开始时间:2.20
双指针
1 盛最多水的容器
class Solution(object):
def maxArea(self, height):
"""
:type height: List[int]
:rtype: int
"""
# 暴力解法 12ms超时
# res = 0
# for i in range(len(height)):
# for j in range(i+1, len(height)):
# l = j -i
# h = min(height[i], height[j])
# vol = l * h
# res = max(vol, res)
# return res
# 双指针 !
l = 0 #left pointer
r = len(height) - 1 #right pointer
res = 0
while l < r :
vol = (r - l) * min(height[l], height[r])
res = max(res, vol)
if height[l] <= height[r]:
l += 1
else:
r -= 1
return res
2 三数之和
我的解法: 写了一个世纪┭┮﹏┭┮,虽然通过,但太长,运行时间也长
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
nums = sorted(nums)
res = []
j = 1
for i in nums[:len(nums)-2]:
if len(self.twoSum(nums[j:], -i))>0:
for num in self.twoSum(nums[j:], -i):
tmp = []
tmp.append(i)
tmp.extend(num)
res.append(tmp)
j += 1
# 去除res中重复的元素
# print(res)
res_tuples = [tuple(sorted(r)) for r in res] #对每个list元素排序且转为tuple
res_unique = set(res_tuples) #去重,set()函数的操作对象是list、tuple和字符串
res = [list(u) for u in res_unique] #还原为list
return res
@staticmethod
def twoSum(array, addvalue):
res =[]
if len(array) >= 2:
lp = 0
rp = len(array)-1
while lp < rp:
if array[lp] + array[rp] < addvalue:
lp += 1
elif array[lp] + array[rp] > addvalue:
rp -= 1
else:
tmp = []
tmp.append(array[lp])
tmp.append(array[rp])
res.append(tmp)
lp += 1
rp -= 1
continue
return res
leetcode官方题解:很简洁(┭┮﹏┭┮)
class Solution:
def threeSum(self, nums):
n = len(nums)
nums.sort()
ans = list()
# 枚举 a
for first in range(n):
# 需要和上一次枚举的数不相同
if first > 0 and nums[first] == nums[first - 1]:
continue
# c 对应的指针初始指向数组的最右端
third = n - 1
target = -nums[first]
# 枚举 b
for second in range(first + 1, n):
# 需要和上一次枚举的数不相同
if second > first + 1 and nums[second] == nums[second - 1]:
continue
# 需要保证 b 的指针在 c 的指针的左侧
while second < third and nums[second] + nums[third] > target:
third -= 1
# 如果指针重合,随着 b 后续的增加
# 就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环
if second == third:
break
if nums[second] + nums[third] == target:
ans.append([nums[first], nums[second], nums[third]])
return ans
3 接雨水
class Solution(object):
def trap(self, height):
"""
:type height: List[int]
:rtype: int
"""
n = len(height)
# 每个区域S = min(前缀max,后缀max)-height[i]
pre_max = [0] * n
pre_max[0] = height[0]
for i in range(1, n):
pre_max[i] = max(height[i], pre_max[i-1])
post_max = [0] * n
post_max[-1] = height[-1]
for j in range(n-2, -1 ,-1):
post_max[j] = max(post_max[j+1], height[j])
ans = 0
for pre, post, h in zip(pre_max, post_max, height):
ans += min(pre, post) - h
return ans
# 灵茶山艾府思路
二分查找
一个有序整数数组nums, 查找target在其中的位置,如果nums含有target,则返回其下标,如果不含有targrt,则返回按顺序target应该在哪个位置插入nums。(无论nums中有无重复元素均成立)
def binary_search_insertion(nums: list[int], target: int) -> int:
i, j = 0, len(nums) - 1
while i <= j:
m = (i + j) // 2
if nums[m] < target:
i = m + 1
elif nums[m] > target:
j = m - 1
else:
j = m - 1
return i
查找左右位置,如
nums = [1, 3, 6, 6, 6, 12, 15]
taget = 6
target 左侧位置即为2, 右侧位置为4, 如果要查找的target不存在,则左右位置均返回-1
利用上述二分算法binary_search_insertion(nums, target)
# 左
def binary_search_left_edge(nums: list[int], target: int) -> int:
i = binary_search_insertion(nums, target)
if i == len(nums) or nums[i] != target:
# 越界 或 值不对应
return -1
return i
# 右
def binary_search_right_edge(nums: list[int], target: int) -> int:
i = binary_search_insertion(nums, target + 1)
j = i - 1
if j == -1 or nums[j] != target:
# 首元素 或 值不对应
return -1
return j
(参考10.1 二分查找 - Hello 算法 (hello-algo.com))
4 搜索插入位置
class Solution(object):
def searchInsert(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
i, j = 0, len(nums) - 1
while i <= j:
m = (i + j) //2
if nums[m] < target:
i = m + 1
elif nums[m] > target:
j = m -1
else:
j = m - 1
return i
5 搜索二维矩阵
class Solution(object):
def searchMatrix(self, matrix, target):
"""
:type matrix: List[List[int]]
:type target: int
:rtype: bool
"""
nums = []
for item in matrix:
nums.extend(item)
i = self.searchInsert(nums, target)
if i == len(nums) or nums[i] != target:
return False
return True
@staticmethod
def searchInsert(nums, target):
i, j = 0, len(nums) - 1
while i <= j:
m = (i + j) // 2
if nums[m] < target:
i = m + 1
elif nums[m] > target:
j = m - 1
else:
j = m - 1
return i
6 在排序数组中查找元素的第一个和最后一个位置
class Solution(object):
def searchRange(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
left = self.searchInsert(nums, target)
if left == len(nums) or nums[left] != target:
left = -1
right = self.searchInsert(nums, target + 1) - 1
if right == -1 or nums[right] != target:
right = -1
return [left, right]
@staticmethod
def searchInsert(nums, target):
i, j = 0, len(nums) - 1
while i <= j:
m = (i + j) // 2
if nums[m] < target:
i = m + 1
elif nums[m] > target:
j = m - 1
else:
j = m - 1
return i
7 搜索旋转排序数组(⭐)
看答案的。
class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
l, r = 0, len(nums) - 1
while l <= r:
m = (l + r) // 2
if nums[m] == target:
return m
# 总有一侧是有序的,如果左侧有序
if nums[0] <= nums[m]:
if nums[0] <= target < nums[m]:
r = m - 1
else:
l = m + 1
else:
if nums[m] < target <= nums[len(nums) - 1]:
l = m + 1
else:
r = m - 1
return -1
8 寻找旋转排序数组中的最小值(⭐)
看答案的。
class Solution(object):
def findMin(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
l, r = 0 ,len(nums) - 1
while l < r:
m = (l + r) // 2
if nums[m] < nums[r]:
r = m
elif nums[m] > nums[r]:
l = m + 1
return nums[l]
滑动窗口
最长不重复子串
思路:左指针left, 右指针right, 在右指针向右移动的过程中,如果nums[right]不在set()里面,则加入,如果在set()里面,则先不右移,将左指针向右移动,并在set()里面删除nums[left], 直到可以右移右指针为止。
9 无重复字符的最长子串(⭐)
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
left, right, length, max_length = 0, 0, 0, 0
array = set()
while right < len(s):
if s[right] not in array:
array.add(s[right])
right += 1
length += 1
max_length = max(length, max_length)
else:
while s[right] in array:
array.remove(s[left])
left += 1
length -= 1
array.add(s[right])
right += 1
length += 1
return max_length
10 找到字符串中所有字母异位词(⭐)
维护两个数组,长度为26,每一个位置表示某个字母的出现位置,比较这两个数组,一直则为异位词。
class Solution(object):
def findAnagrams(self, s, p):
"""
:type s: str
:type p: str
:rtype: List[int]
"""
n = len(s)
m = len(p)
res = []
if n < m:
return res
s_count = [0] * 26
p_count = [0] * 26
for i in range(m):
p_count[ord(p[i]) - ord('a')] += 1
s_count[ord(s[i]) - ord('a')] += 1
if p_count == s_count:
res.append(0)
for i in range(m, n):
s_count[ord(s[i-m]) - ord('a')] -= 1
s_count[ord(s[i]) - ord('a')] += 1
if s_count == p_count:
res.append(i-m+1)
return res
回溯
全排列(参考13.2 全排列问题 - Hello 算法 (hello-algo.com))
无重复元素
[1, 2, 3]
全排列[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
[1, 1, 3]
全排列[[1, 1, 3], [1, 3, 1], [1, 1, 3], [1, 3, 1], [3, 1, 1], [3, 1, 1]]
def backtrack(state, choices, selected, res):
"""回溯算法:全排列 I"""
# 当状态长度等于元素数量时,记录解
if len(state) == len(choices):
res.append(list(state))
return
# 遍历所有选择
for i, choice in enumerate(choices):
# 剪枝:不允许重复选择元素
if not selected[i]:
# 尝试:做出选择,更新状态
selected[i] = True
state.append(choice)
# 进行下一轮选择
backtrack(state, choices, selected, res)
# 回退:撤销选择,恢复到之前的状态
selected[i] = False
state.pop()
def permutations_i(nums):
res = []
backtrack(state=[], choices=nums, selected=[False] * len(nums), res=res)
return res
有重复元素
[1, 1, 3]全排列[[1, 1, 3], [1, 3, 1], [3, 1, 1]]
def backtrack2(state, choices, selected, res):
if len(state) == len(choices):
res.append(list(state))
return
duplicated = set[int]() #add
for i, choice in enumerate(choices):
if not selected[i] and choice not in duplicated: #add
duplicated.add(choice) #add
state.append(choice)
selected[i] = True
backtrack2(state, choices, selected, res)
selected[i] = False
state.pop()
def permutations_i2(nums):
res = []
backtrack2(state=[], choices=nums, selected=[False] * len(nums), res=res)
return res
print(permutations_i2([1,1,3]))
11 全排列
class Solution(object):
def permute(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
def backtrack(state, choices, selected, res):
if len(state) == len(choices):
res.append(list(state))
return
for i, choice in enumerate(choices):
if not selected[i]:
selected[i] = True
state.append(choice)
backtrack(state, choices,selected, res)
selected[i] = False
state.pop()
res = []
backtrack([], nums, [False]*len(nums), res)
return res