返回
算法练习日志二:最大子序和+假币问题
闲谈
2023-10-13 00:44:51
最大子序和(单调队列)
最大子序和问题是指在一个序列中找到一个连续的子序列,使得子序列的和最大。
解法一:暴力法
暴力法的思路很简单,就是枚举所有可能的子序列,然后计算每个子序列的和,最后输出最大的那个子序列的和。
def max_subarray_sum_brute_force(arr):
max_sum = float('-inf')
for i in range(len(arr)):
for j in range(i + 1, len(arr) + 1):
subarray = arr[i:j]
subarray_sum = sum(subarray)
max_sum = max(max_sum, subarray_sum)
return max_sum
解法二:单调队列
单调队列是一个先进先出的队列,队列中的元素始终保持单调递减。
单调队列可以用来解决最大子序和问题,思路是将队列中的元素从小到大排序,然后将每个元素依次加入队列。当队列中的元素个数大于等于给定的窗口大小时,将队首元素弹出队列。最后,队列中剩下的元素就是最大子序和的子序列。
def max_subarray_sum_deque(arr, window_size):
if window_size > len(arr):
return float('-inf')
# 创建一个单调队列
deque = collections.deque()
# 将第一个窗口的元素加入队列
for i in range(window_size):
while deque and arr[i] >= arr[deque[-1]]:
deque.pop()
deque.append(i)
# 将剩下的元素依次加入队列
max_sum = arr[deque[0]]
for i in range(window_size, len(arr)):
# 如果队首元素不在当前窗口中,将队首元素弹出队列
while deque and deque[0] <= i - window_size:
deque.popleft()
# 将当前元素加入队列
while deque and arr[i] >= arr[deque[-1]]:
deque.pop()
deque.append(i)
# 更新最大子序和
max_sum = max(max_sum, arr[deque[0]])
return max_sum
假币问题(枚举法)
假币问题是指有一堆硬币,其中有一枚是假的,假的硬币比其他硬币轻。
枚举法的思路很简单,就是枚举所有的硬币,然后用天平称量每一枚硬币。如果某一枚硬币比其他硬币轻,那么它就是假的硬币。
def find_fake_coin(coins):
# 将硬币分为两堆
n = len(coins)
pile1 = coins[:n // 2]
pile2 = coins[n // 2:]
# 称量两堆硬币
if sum(pile1) == sum(pile2):
# 假币在剩下的硬币中
return find_fake_coin(coins[n // 2:])
elif sum(pile1) > sum(pile2):
# 假币在第一堆硬币中
return find_fake_coin(pile1)
else:
# 假币在第二堆硬币中
return find_fake_coin(pile2)