题目:
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。
注意你不能在买入股票前卖出股票。
示例 1:
输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
示例 2:
输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
代码:
/**
* @作者:dhc
* @创建时间:13:26 2018/8/9
* @描述:121、买股票的最佳时机
*/
public class OneHundredAndTwentyOne {
//方法三
// 思路:就想到首先从第一个元素开始循环,第一个元素作为最小元素,如果后面的元素比他小,就替换为最小元素,如果
//某个元素和当前最小元素的差比之前保存的最大利润大,就更新最大利润。
//最开始的时候因为分类是动态规划,就网这方面想,但是最优子结构没想出来怎么构建和重复子问题也不是很
// 清除,然后在准备开始写方法二的时候就想着O(n)的时间和空间,感觉和最大字段和有点相似但有不同,所以根据实际
//问题,
public static int maxProfit2(int[] prices) {
if(prices.length < 2){
return 0;
}
int max = 0;
int minNum = prices[0];
int tem = 0;
for (int i = 0; i < prices.length; i++) {
tem = prices[i] - minNum;
if(tem < 0){
minNum = prices[i];
}
if (tem > max) {
max = tem;
}
}
return max;
}
//方法一:直接想到的就是双重循环遍历所有的情况,n放的时间复杂度和常数空间
public static int maxProfit(int[] prices) {
int max = 0;
int tem = 0;
for (int i = 0; i < prices.length; i++) {
for(int j = i + 1;j < prices.length;j++){
tem = prices[j] - prices[i];
if(tem > max){
max = tem;
}
}
}
return max;
}
//方法二:在写完双重循环后,又想到这个最大值就是用数组中的最大值减去数组中的最小值
//不过有个条件就是最大值要在最小值的前面,如果不是则判断最小值和第二大值的位置,因此
//就要对数组排序,不过不是直接排序,而是将数组的下标按照数组元素值的大小依次存在一个数组
//中,并且找出最小值和最小值的下标,然后依次比较较大值而最小值的下标位置关系,知道找出
//最大利润。这个方法要用到O(n)的空间,在在最后比较的这一步时间最差是O(n),但是有个下标排序
//,想到的是插入法,所以又需要O(n)的时间,但是还要移动元素,最差是O(n2),所以也不是很好
public static int maxProfit1(int[] prices) {
int max = 0;
return max;
}
}