目录
1014. 最佳观光组合
问题描述
给你一个正整数数组 values
,其中 values[i]
表示第 i
个观光景点的评分,并且两个景点 i
和 j
之间的 距离 为 j - i
。
一对景点(i < j
)组成的观光组合的得分为 values[i] + values[j] + i - j
,也就是景点的评分之和 减去 它们两者之间的距离。返回一对观光景点能取得的最高分。
示例 1:
输入:values = [8,1,5,2,6] 输出:11 解释:i = 0, j = 2, values[i] + values[j] + i - j = 8 + 5 + 0 - 2 = 11
示例 2:
输入:values = [1,2] 输出:2
提示:
2 <= values.length <= 5 * 10^4
1 <= values[i] <= 1000
思路与算法
记代表景点(i < j
)组成的观光组合的得分,
考虑表示从0到j
的序列满足题设要求的最高分,问题所求的就是。直观地求需要遍历,这样的话总的复杂度就是。
但是,将分数计算公式做一个变形得到:values[i] + i + values[j] - j,对于
的计算来说,后半部分是固定的,因此只要找到前半部分的最大值即可得到如下所示:
进一步,在对的遍历过程中,的计算是可以以迭代的方式进行维护和更新的,这样,的计算复杂度就变成,总的复杂度变成。
代码实现
class Solution:
def maxScoreSightseeingPair(self, values: List[int]) -> int:
# Initialization for (0,1)
max_vi_plus_i = values[0] + 0
# vj_minus_j = nums[1] - 1
max_score = max_vi_plus_i + values[1] - 1
for j in range(2,len(values)):
max_vi_plus_i = max(max_vi_plus_i,values[j-1]+j-1)
max_score = max(max_score,max_vi_plus_i + values[j] - j)
return max_score
执行用时:188 ms, 在所有 Python3 提交中击败了13.63%的用户
内存消耗:19.7 MB, 在所有 Python3 提交中击败了77.22%的用户
121. 买卖股票的最佳时机
问题描述
给定一个数组 prices
,它的第 i
个元素 prices[i]
表示一支给定股票第 i
天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0
。
示例 1:
输入:[7,1,5,3,6,4] 输出:5 解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
示例 2:
输入:prices = [7,6,4,3,1] 输出:0 解释:在这种情况下, 没有交易完成, 所以最大利润为 0。
提示:
1 <= prices.length <= 10^5
0 <= prices[i] <= 10^4
思路与算法
买入必须发生卖出之前。
考虑代表在day#j卖出该股票所能获得的最大利益。那最终结果就等于。
要确保在day#j卖出时的利益最大化,必要day#j之前的最低价时买入该股票。这样可以得到:
而针对每个j的买入最低价是可以以迭代的方式处理,只有,因此总的复杂度为。
代码实现
class Solution:
def maxProfit(self, prices: List[int]) -> int:
minprice = prices[0]
maxprofit= -prices[0]
for j in range(1,len(prices)):
profit = prices[j] - minprice
minprice = min(minprice,prices[j])
maxprofit= max(maxprofit,profit)
return max(maxprofit,0)
执行用时:280 ms, 在所有 Python3 提交中击败了42.33%的用户
内存消耗:23.6 MB, 在所有 Python3 提交中击败了15.69%的用户
122. 买卖股票的最佳时机 II
问题描述
给你一个整数数组 prices
,其中 prices[i]
表示某支股票第 i
天的价格。
在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。返回 你能获得的 最大 利润 。
示例 1:
输入:prices = [7,1,5,3,6,4] 输出:7 解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。 随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3 。 总利润为 4 + 3 = 7 。
示例 2:
输入:prices = [1,2,3,4,5] 输出:4 解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。 总利润为 4 。
示例 3:
输入:prices = [7,6,4,3,1] 输出:0 解释:在这种情况下, 交易无法获得正利润,所以不参与交易可以获得最大利润,最大利润为 0 。
提示:
1 <= prices.length <= 3 * 10^4
0 <= prices[i] <= 10^4
思路与算法
在任何一天,只要该天的股价为局部极大点那么都应该在之前最近的一个极小点买入然后在当天卖出。问题描述中“你也可以先购买,然后在 同一天 出售。”,这句话与什么用意,感觉难道不是一句废话吗?
所以,基本操作规则如下:从左到右遍历,碰到极小点就买入,碰到极大点就卖出。
但是中间出现平台区会使得判断比较麻烦。以下以一个有限状态机的方式来求解本题(虽然是动态规划系列,但是感觉用有限状态机的方式更易懂,而且偶尔换点口味也不错)
代码实现
class Solution:
def maxProfit(self, prices: List[int]) -> int:
state, bought, profit = 0,0,0
prices.append(0) # Appending one zero for the convenience of last day handling
for i in range(len(prices)-1):
if state == 0:
if prices[i+1]>prices[i]:
bought = prices[i]
state = 1
elif prices[i+1]<prices[i]:
state = -1
elif state == -1:
if prices[i+1]>prices[i]:
bought = prices[i]
state = 1
else:
if prices[i+1]<prices[i]:
state = -1
profit += prices[i]-bought
# print(i,state,bought, profit)
return profit
if __name__ == "__main__":
sln = Solution()
prices = [7,1,5,3,6,4]
print(sln.maxProfit(prices))
prices = [7,6,4,3,1]
print(sln.maxProfit(prices))
prices = [7,6,4,3,6]
print(sln.maxProfit(prices))
prices = [1,2,3,4,5]
print(sln.maxProfit(prices))
执行用时:36 ms, 在所有 Python3 提交中击败了88.26%的用户
内存消耗:16.1 MB, 在所有 Python3 提交中击败了21.77%的用户
回到总目录:笨牛慢耕的Leetcode每日一题总目录(动态更新。。。)