"The Road to Algorithm Clearance" study notes, record your own process of brushing the questions, please buy the author's book for detailed content.
Majority II
Retweet question 229
Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times.
'''
方法一:摩尔投票法
时间复杂度: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]
The largest rectangle in the histogram
Lituo question 84
Given n non-negative integers, used to represent the height of each column in the histogram. Each column is adjacent to each other and has a width of 1.
Find the maximum area of the rectangle that can be outlined in the histogram.
'''
方法一:双层循环(超时)
时间复杂度: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
day of the week
Lituo question 1185.
Given a date, please design an algorithm to determine which day of the week it corresponds to.
'''
时间复杂度: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'
kettle problem
Leetok question 365
There are two water jugs with capacities of jug1Capacity and jug2Capacity liters respectively. The supply of water is unlimited. Determines whether it is possible to get targetCapacity liters exactly using both jugs.
If targetCapacity liters of water are available, use one or two of the above jugs at the end to hold the targetCapacity liters obtained.
you can:
Fill any jug
Empty any jug
Pour water from one jug to another until full or empty
'''
方法一: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
poor pig
Lituo No. 458
There are buckets of liquid, one of which contains poison, and the rest are filled with water. They all look the same from the outside. To figure out which bucket contains the poison, you can feed some pigs to drink and see if the pigs die. Unfortunately, you only have minutesToTest minutes to determine which bucket of liquid is poisonous.
The rules for feeding pigs are as follows:
Selecting several live pigs for feeding
allows piglets to drink from any number of buckets at the same time, and the process does not take time.
After the piglet drinks the water, there must be a cooling time of minutesToDie minutes. During this time, you can only observe and are not allowed to continue feeding the pigs.
After minutesToDie minutes have elapsed, all pigs that drink the poison will die, and all other pigs will survive.
Repeat this process until time runs out.
Given the number of buckets buckets, minutesToDie and minutesToTest, return the minimum number of pigs needed to determine which bucket is poisonous within the specified time.
'''
方法一:搜索法
时间复杂度: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