《算法通关之路》学习笔记,记录一下自己的刷题过程,详细的内容请大家购买作者的书籍查阅。
力扣第229题
给定一个大小为 n 的整数数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。
'''
方法一:摩尔投票法
时间复杂度:O(n)
空间复杂度:O(1)
'''
class Solution:
def majorityElement(self, nums: list[int]) -> list[int]:
n = len(nums)
res = []
cnt1 = 0
cnt2 = 0
n1 = None
n2 = None
# 筛选出出现次数最多的前两个元素
for num in nums:
if num == n1:
cnt1 += 1
elif num == n2:
cnt2 += 1
elif cnt1 == 0:
n1 = num
cnt1 += 1
elif cnt2 == 0:
n2 = num
cnt2 += 1
else:
cnt1 -= 1
cnt2 -= 1
# 筛选出出现次数超过1/3的元素
cnt1 = 0
cnt2 = 0
for num in nums:
if num == n1:
cnt1 += 1
if num == n2:
cnt2 += 1
if cnt1 > n // 3:
res += [n1]
if cnt2 > n // 3:
res += [n2]
return res
nums = [3,2,3]
solu = Solution()
solu.majorityElement(nums)
[3]
力扣第84题
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
'''
方法一:双层循环(超时)
时间复杂度:O(n2)
空间复杂度:O(1)
'''
class Solution:
def largestRectangleArea(self, heights: list[int]) -> int:
n, ans = len(heights), 0
if n != 0:
ans = heights[0]
for i in range(n):
height = heights[i]
for j in range(i, n):
height = min(height, heights[j]) # 最小高度
ans = max(ans, (j-i+1)*height) # 最大面积
return ans
heights = [2,1,5,6,2,3]
solu = Solution()
solu.largestRectangleArea(heights)
10
'''
方法二:中心扩展法(超时)
时间复杂度:O(n2)
空间复杂度:O(1)
'''
class Solution:
def largestRectangleArea(self, heights: list[int]) -> int:
n = len(heights)
ans = 0
# 计算左边第一个高度小于heights[i]的索引和右边第一个小于heights[i]的索引
for i in range(0, n):
j = i - 1
while j >= 0 and heights[j] >= heights[i]:
j -= 1
k = i + 1
while k < n and heights[k] >= heights[i]:
k += 1
# 以i为最低点情况形成的最大矩阵面积
ans = max(ans, heights[i] * (k - j - 1))
return ans
heights = [2,1,5,6,2,3]
solu = Solution()
solu.largestRectangleArea(heights)
10
'''
方法三:中心扩展法(优化)
时间复杂度:O(n)
空间复杂度:O(n)
'''
class Solution:
def largestRectangleArea(self, heights: list[int]) -> int:
n = len(heights)
l, r, ans = [-1]*n, [n]*n, 0
for i in range(0, n):
j = i - 1
while j >= 0 and heights[j] >= heights[i]:
j = l[j] # 优化
l[i] = j
for i in range(n-2, -1, -1):
k = i + 1
while k < n and heights[k] >= heights[i]:
k = r[k] # 优化
r[i] = k
for i in range(n):
ans = max(ans, heights[i] * (r[i] - l[i] - 1))
return ans
heights = [2,1,5,6,2,3]
solu = Solution()
solu.largestRectangleArea(heights)
10
'''
方法四:单调栈
时间复杂度:O(n)
空间复杂度:O(n)
'''
class Solution:
def largestRectangleArea(self, heights: list[int]) -> int:
n, heights, st, ans = len(heights), [0]+heights+[0], [], 0
for i in range(n+2):
while st and heights[st[-1]] > heights[i]:
ans = max(ans, heights[st.pop(-1)]*(i-st[-1]-1))
st.append(i)
return ans
heights = [2,1,5,6,2,3]
solu = Solution()
solu.largestRectangleArea(heights)
10
力扣第1185题
给你一个日期,请你设计一个算法来判断它是对应一周中的哪一天。
'''
时间复杂度:O(n)
空间复杂度:O(1)
'''
class Solution:
def dayOfTheWeek(self, day: int, month: int, year: int) -> str:
months = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
leap_months = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
# 1971-01-01为基准日期,是周五
days = [
'Friday',
'Saturday',
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday'
]
diff = 0
# 处理年
for i in range(1971, year):
if i % 400 == 0 or (i % 4 == 0 and i % 100 != 0):
diff += 1
diff += (year - 1971) * 365
# 处理月
for m in range(month - 1):
if year % 400 == 0 or (year % 4 == 0 and year % 100 != 0):
diff += leap_months[m]
else:
diff += months[m]
# 处理日
diff += day - 1
return days[diff % 7]
day, month, year = 31, 8, 2019
solu = Solution()
solu.dayOfTheWeek(day, month, year)
'Saturday'
力扣第365题
有两个水壶,容量分别为 jug1Capacity 和 jug2Capacity 升。水的供应是无限的。确定是否有可能使用这两个壶准确得到 targetCapacity 升。
如果可以得到 targetCapacity 升水,最后请用以上水壶中的一或两个来盛放取得的 targetCapacity 升水。
你可以:
装满任意一个水壶
清空任意一个水壶
从一个水壶向另外一个水壶倒水,直到装满或者倒空
'''
方法一:DFS(超时)
'''
class Solution:
def canMeasureWater(self, x: int, y: int, z: int) -> bool:
def dfs(x: int, y: int, z: int, state: set) -> bool:
a, b = state
if a == z or b == z or a + b == z:
return True
seen.add((a, b))
states = set()
states.add((x, b)) # 将x的水盛满
states.add((a, y)) # 将y的水盛满
states.add((0, b)) # 将x的水倒空
states.add((a, 0)) # 将y的水倒空
states.add((min(x, b + a), 0 if b < x - a else b - (x-a))) # 将x的水全部倒给y
states.add((0 if a < y - b else a - (y - b), min(b + a, y))) # 将y的水全部倒给x
res = False
for state in states:
if state in seen:
res |= False
else:
res |= dfs(x, y, z, state)
return res
if x + y < z:
return False
state = (0, 0)
seen = set(state)
return dfs(x, y, z, state)
x, y, z = 3, 5, 4
solu = Solution()
solu.canMeasureWater(x, y, z)
True
'''
方法二:BFS
时间复杂度:O(xy)
空间复杂度:O(xy)
'''
class Solution:
def canMeasureWater(self, x: int, y: int, z: int) -> bool:
if x + y < z:
return False
queue = [(0, 0)]
seen = set((0, 0))
while len(queue) > 0:
a, b = queue.pop(0)
if a == z or b == z or a + b == z:
return True
states = set()
states.add((x, b)) # 将x的水盛满
states.add((a, y)) # 将y的水盛满
states.add((0, b)) # 将x的水倒空
states.add((a, 0)) # 将y的水倒空
states.add((min(x, b + a), 0 if b < x - a else b - (x-a))) # 将x的水全部倒给y
states.add((0 if a < y - b else a - (y - b), min(b + a, y))) # 将y的水全部倒给x
for state in states:
if state in seen:
continue
queue.append(state)
seen.add(state)
return False
x, y, z = 3, 5, 4
solu = Solution()
solu.canMeasureWater(x, y, z)
True
'''
方法三:最大公约数
时间复杂度:O(log(max(a, b)))
空间复杂度:O(min(a, b))
'''
class Solution:
def canMeasureWater(self, x: int, y: int, z: int) -> bool:
if x + y < z:
return False
if z == 0:
return True
if x == 0:
return y == z
if y == 0:
return x == z
def GCD(a: int, b:int) -> int:
return a if b == 0 else GCD(b, a % b)
return z % GCD(x, y) == 0
x, y, z = 3, 5, 4
solu = Solution()
solu.canMeasureWater(x, y, z)
True
力扣第458题
有 buckets 桶液体,其中 正好有一桶 含有毒药,其余装的都是水。它们从外观看起来都一样。为了弄清楚哪只水桶含有毒药,你可以喂一些猪喝,通过观察猪是否会死进行判断。不幸的是,你只有 minutesToTest 分钟时间来确定哪桶液体是有毒的。
喂猪的规则如下:
选择若干活猪进行喂养
可以允许小猪同时饮用任意数量的桶中的水,并且该过程不需要时间。
小猪喝完水后,必须有 minutesToDie 分钟的冷却时间。在这段时间里,你只能观察,而不允许继续喂猪。
过了 minutesToDie 分钟后,所有喝到毒药的猪都会死去,其他所有猪都会活下来。
重复这一过程,直到时间用完。
给你桶的数目 buckets ,minutesToDie 和 minutesToTest ,返回 在规定时间内判断哪个桶有毒所需的 最小 猪数 。
'''
方法一:搜索法
时间复杂度:O(logn)
空间复杂度:O(1)
'''
class Solution:
def poorPigs(self, buckets: int, minutesToDie: int, minutesToTest: int) -> int:
cnt = 0
while(minutesToTest // minutesToDie + 1) ** cnt < buckets:
cnt += 1
return cnt
buckets, minutesToDie, minutesToTest = 1000, 15, 60
solu = Solution()
solu.poorPigs(buckets, minutesToDie, minutesToTest)
5
import math
'''
方法二:n分法
时间复杂度:O(logn)
空间复杂度:O(1)
'''
class Solution:
def poorPigs(self, buckets: int, minutesToDie: int, minutesToTest: int) -> int:
states = minutesToTest // minutesToDie + 1
return math.ceil(math.log(buckets) / math.log(states) - 1e-5)
buckets, minutesToDie, minutesToTest = 1000, 15, 60
solu = Solution()
solu.poorPigs(buckets, minutesToDie, minutesToTest)
5
笔记本-Github