131 价格优惠计算问题
问题描述
小F在“双十一”期间购买了N件商品。每件商品有一个价格p[i],小F可以获得的优惠取决于该商品之前的一件商品。如果某一件商品的价格p[i]大于等于前面的某个商品p[j],则小F可以享受该商品]p[j]的价格作为优惠,前提是p[j]是离p[i]最近的且满足条件的商品。
例如,给定价格数组p = [9, 4, 5, 2, 4],其中p[3] = 2之前没有商品的价格小于等于p[3],因此没有优惠;而p[2] = 5可以享受最近的商品p[1] = 4的价格作为优惠。因此,任务是计算小F能获得的总优惠。
解题思路
找到某个商品p[i]之前第一个小于等于p[i]价格的商品p[j]。
-
初始化:
- 创建一个空栈
stack用于存储商品价格。 - 初始化
discount变量为 0,用于累计总优惠。
- 创建一个空栈
-
遍历价格数组:
- 对于每个价格
price,检查栈顶元素是否大于当前价格。 - 如果栈顶元素大于当前价格,则弹出栈顶元素,直到栈为空或栈顶元素小于等于当前价格。
- 如果栈不为空,说明当前价格可以享受栈顶元素的价格作为优惠,因此将栈顶元素的值加到
discount中。 - 将当前价格
price压入栈中。
- 对于每个价格
-
返回结果:
- 遍历结束后,返回
discount作为总优惠。
- 遍历结束后,返回
def solution(N: int, p: list) -> int:
stack = []
discount = 0
for price in p:
while stack and stack[-1] > price:
stack.pop()
if stack:
discount += stack[-1]
stack.append(price)
return discount
122 最大乘积问题
问题描述
小R最近遇到了一个数组问题。他有一个包含 N 个元素的数组,记作a1,a2,...,aN。为了分析这个数组的特性,小R定义了两个函数 L(i) 和 R(i),并希望通过这两个函数来找到一些有趣的结论。
L(i) 是满足以下条件的最大的 j 值:
j<ia[j]>a[i]- 如果找不到这样的 j,那么
L(i)=0;如果有多个满足条件的 j,选择离 i 最近的那个。
R(i) 是满足以下条件的最小的 k 值:
k>ia[k]>a[i]- 如果找不到这样的 k,那么
R(i)=0;如果有多个满足条件的 k,选择离 i 最近的那个。
最终,小R定义MAX(i)=L(i)∗R(i),他想知道在 1≤i≤N 的范围内,MAX(i) 的最大值是多少。
解题思路
需要找到数组中每个元素的 L(i) 和 R(i),然后计算 MAX(i) = L(i) * R(i),并找出这个值的最大值。可以使用栈维护两个递减的序列,从而快速找到每个元素的 L(i) 和 R(i)。
-
初始化
L和R数组:L和R列表用于存储每个元素的L(i)和R(i)值。
-
计算
L(i):- 从左到右遍历数组,使用栈来维护递减的序列。
- 对于每个元素
a[i],如果栈不为空且栈顶元素小于等于a[i],则弹出栈顶元素,直到找到一个大于a[i]的元素或栈为空。 - 如果栈不为空,
L(i)为栈顶元素的索引+1,否则默认为0。 - 当前元素入栈。
-
计算
R(i):- 从右到左遍历数组,使用栈来维护递减的序列。
- 对于每个元素
a[i],如果栈不为空且栈顶元素小于等于a[i],则弹出栈顶元素,直到找到一个大于a[i]的元素或栈为空。 - 如果栈不为空,
R(i)为栈顶元素的索引+1,否则默认为0。 - 当前元素入栈。
-
计算
MAX(i)并找到最大值:- 遍历列表,计算每个
i的MAX(i) = L(i) * R(i)。 - 记录并返回
MAX(i)的最大值。
- 遍历列表,计算每个
def solution(n, array):
L = [0]*n
R = [0]*n
# 使用栈来计算 L(i)
stack = []
for i in range(n):
# 当栈不为空且栈顶元素小于等于当前元素时,弹出栈顶元素
while stack and array[stack[-1]] <= array[i]:
stack.pop()
# 如果栈不为空,L(i) 为栈顶元素的索引+1
if stack:
L[i] = stack[-1] + 1
stack.append(i)
# 清空栈,用于计算 R(i)
stack = []
#从右向左遍历数组
for i in range(n-1,-1,-1):
# 当栈不为空且栈顶元素小于等于当前元素时,弹出栈顶元素
while stack and array[stack[-1]] <= array[i]:
stack.pop()
# 如果栈不为空,R(i) 为栈顶元素的索引+1
if stack:
R[i] = stack[-1] + 1
stack.append(i)
# 计算 MAX(i) 并找到最大值
result = 0
for i in range(n):
result = max(result,L[i]*R[i])
return result
139 套碗游戏的取碗顺序问题
问题描述
小F正在玩一个套碗的游戏,每个碗都有一个编号,从1到n,它们从大到小被套在一根木棍上。小F只能从木棍上取最上面的碗,每次只能取一个。现在你需要判断给定的取碗顺序是否可行。如果可行,那么返回1,否则返回0。
例如,对于2个碗,取碗的顺序可以是 2 1 或 1 2,这两种顺序都是合法的。而对于3个碗,给定顺序 3 1 2 不可能通过合法操作实现,因此该顺序不可行。
解题思路
没看懂题目,根据样例来看,是将1-n从小到大按顺序进栈,判断出栈顺序是否合法。
-
初始化:
- 创建一个空栈
stack,用于模拟碗的进栈和出栈操作。 - 初始化一个指针
current,指向当前需要进栈的碗的编号,初始值为1。
- 创建一个空栈
-
遍历出栈顺序:
- 遍历给定的出栈顺序
a中的每一个元素num。
- 遍历给定的出栈顺序
-
栈操作:
-
对于每一个
num,检查栈顶元素是否等于num:- 如果栈顶元素等于
num,则弹出栈顶元素。 - 如果栈顶元素不等于
num,则将当前编号的碗(即current)进栈,并将current加1。 - 如果
current超过了总数M,则说明无法继续进栈,出栈顺序不合法,返回0。
- 如果栈顶元素等于
-
-
返回结果:
- 如果所有碗都正确进栈并出栈,且
current等于M + 1,则返回1,表示出栈顺序合法。 - 否则返回
0,表示出栈顺序不合法。
- 如果所有碗都正确进栈并出栈,且
def solution(M: int, a: list) -> int:
stack = [] # 初始化一个空栈,用于模拟碗的进栈和出栈操作
current = 1 # 初始化一个指针,指向当前需要进栈的碗的编号
for num in a: # 遍历给定的出栈顺序
while not stack or stack[-1] != num: # 如果栈为空或栈顶元素不等于当前出栈顺序的元素
if current > M: # 如果当前需要进栈的碗的编号超过了总数 M
return 0 # 返回 0,表示出栈顺序不合法
stack.append(current) # 将当前编号的碗进栈
current += 1 # 指针后移,指向下一个需要进栈的碗
stack.pop() # 如果栈顶元素等于当前出栈顺序的元素,则弹出栈顶元素
return 1 if current == M + 1 else 0 # 如果所有碗都正确进栈并出栈,返回 1,否则返回 0
140 套碗游戏的取碗顺序问题(二)
问题描述
小F正在玩一个套碗的游戏,每个碗都有一个编号,从1到n,它们从大到小被套在一根木棍上。小F只能从木棍上取最上面的碗,每次只能取一个。现在你需要计算总共有多少种取碗的顺序。
例如,对于2个碗,取碗的顺序可以是 2 1 或 1 2,这两种顺序都是合法的。而对于3个碗,给定顺序 3 1 2 不可能通过合法操作实现,因此该顺序不可行。
解题思路
同上题,将1-n从小到大按顺序进栈,计算有多少种合法的出栈顺序。
可以使用卡特兰数(Catalan Number)来计算。卡特兰数是一个在组合数学中常见的数列,用于解决许多组合问题,包括栈的出栈顺序问题。
-
卡特兰数:
- 卡特兰数
C(n)表示n个元素的出栈顺序的数量。 - 卡特兰数的递推公式为:
- 初始条件为
C(0) = 1。
- 卡特兰数
-
计算卡特兰数:
- 这是一个递推的过程,可以使用动态规划来计算卡特兰数。
- 创建一个数组
catalan,其中catalan[i]表示i个元素的出栈顺序的数量。 - 根据递推公式计算每个
catalan[i]。
def solution(n):
# 初始化卡特兰数数组
catalan = [0] * (n + 1)
# 初始条件
catalan[0] = 1
# 计算卡特兰数
for i in range(1, n + 1):
for j in range(i):
catalan[i] += catalan[j] * catalan[i - 1 - j]
return catalan[n]