121. 买卖股票的最佳时机& 1911. 最大子序列交替和
给定一个数组 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。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock
int maxProfit(int* prices, int pricesSize){
int minp=INT_MAX; //最小价格
int max=0; //最大差值
for(int i=0;i<pricesSize;i++){
if(prices[i]<minp) minp=prices[i];
else if(prices[i]-minp>max) max=prices[i]-minp;
}
return max;
}
可以使用fmax和fmin代替
int maxProfit(int* prices, int pricesSize){
int minp=INT_MAX;
int max=0;
for(int i=0;i<pricesSize;i++){
minp=fmin(prices[i],minp);
max=fmax(prices[i]-minp,max);
}
return max;
}
然而后者的运算时间更长
“fmin”和“fmax”函数分别用于查找最小值和最大值。与直接比较运算符相比,这些函数涉及额外的操作和函数调用。此外,这些函数还可能涉及浮点运算。
相比之下,第一个函数使用“<”和“>”直接比较,这是简单的整数比较操作。与“fmin”和“fmax”函数相比,这些操作通常更快,需要更少的计算开销。
回到每日一题 1911. 最大子序列交替和
一个下标从 0 开始的数组的 交替和 定义为 偶数 下标处元素之 和 减去 奇数 下标处元素之 和 。
比方说,数组 [4,2,5,3] 的交替和为 (4 + 5) - (2 + 3) = 4 。
给你一个数组 nums ,请你返回 nums 中任意子序列的 最大交替和 (子序列的下标 重新 从 0 开始编号)。
一个数组的 子序列 是从原数组中删除一些元素后(也可能一个也不删除)剩余元素不改变顺序组成的数组。比方说,[2,7,4] 是 [4,2,3,7,2,1,4] 的一个子序列(加粗元素),但是 [2,4,2] 不是。
示例 1:
输入:nums = [4,2,5,3]
输出:7
解释:最优子序列为 [4,2,5] ,交替和为 (4 + 5) - 2 = 7 。
示例 2:
输入:nums = [5,6,7,8]
输出:8
解释:最优子序列为 [8] ,交替和为 8 。
示例 3:
输入:nums = [6,2,1,2,4,5]
输出:10
解释:最优子序列为 [6,1,5] ,交替和为 (6 + 5) - 1 = 10 。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/maximum-alternating-subsequence-sum
long long maxAlternatingSum(int* nums, int numsSize){
long long left = nums[0], right = 0;
for(int i = 1; i < numsSize; i++){
long long tmp = left;
left = fmax(left, right + nums[i]); //当nums[i]作为偶数下标
right = fmax(right, tmp - nums[i]); //当nums[j]作为奇数下标
}
return left;
}
该函数使用动态编程方法有效计算最大交替和。它从第二个元素(索引1)开始遍历数组nums
。对于索引i
的每个元素,它计算两个值: 左 "和 "右"。
- left "表示如果 "nums[i]"作为子序列中偶数索引处的元素被包含时的最大交替和。
- right 表示如果
nums[i]
是子序列中奇数索引的元素,最大交替和。
为了计算这些值,函数使用了fmax
函数来比较和更新每次迭代的最大交替和。使用的公式如下
tmp = left;
left = fmax(left, right + nums[i])
right = fmax(right, tmp - nums[i])
//由于先存了left的值在tmp里面,所以这里的right中的tmp是没有加新数字的left
//因为把上面的nums[i]移到左边,与下面的fmax判断一致,所以可以判断两种不同的情况
这里,tmp
存储了left
的前一个值,以避免过早覆盖。
在遍历整个数组后,函数返回left
的最终值,它代表给定数组nums
的最大交替和。
比如:
- 在索引1,
left = fmax(4, 0 + 2) = 4
,right = fmax(0, 4 - 2) = 2
。 - 索引2,
左 = fmax(4, 2 + 5) = 7
,右 = fmax(2, 4 - 5) = 2
。 - 索引3,
左 = fmax(7, 2 + 3) = 7
,右 = fmax(2, 7 - 3) = 4
。
在fmax中选定了left则表示把继承前面一个right的值,前面一个数为奇数位的时候可以达到更大值
即使在前面一次比较中比较小,也会保留至下一轮比较中
且保留left的前提是前面已经计算过一次right,right的前提已经计算过一次left,所以可以正常模拟流程