题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/description/?envType=study-plan-v2&envId=top-100-liked
算法思路:
虽然已经提示我们使用贪心算法了,但是我最开始的时候却不知道怎么使用,因为如果我找最小的天购入但是不一定卖的出去(还是有点太全局思维了后来看来题解才明白)。
所以我是每次都找到这天后的最大值,得到一个maxValue数组,这样我们就可以通过maxValue[i] - prices[i]来找到这一天的理想收获。然后遍历找到最大的值。
但是我们怎么计算处maxValue数组呢,暴力肯定不行,所以我们可以通过map来记录我们还未遍历过的数的个数情况,我们每遍历过一个数我们就将他的个数-1,当减成0后我们就从map中移除他,如果我们我们上一次求出的maxV还在map中那么这个数肯定就是maxV,否则我们再去重新求maxV,这样可以极大降低时间复杂度。
代码实现:
public int maxProfit(int[] prices) {
int[] maxPrices = new int[prices.length];
//用map存一下我们还为遍历过的数的个数
HashMap<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < prices.length; i++) {
map.put(prices[i], map.getOrDefault(prices[i], 0) + 1);
}
//当前位置后的最大值
int maxValue = -1;
for(int i = 0; i< prices.length; i++) {
//如果上次算出的最大值还在map中则一直都使用他做最大值
if(maxValue != -1 && map.containsKey(maxValue)) {
maxPrices[i] = maxValue;
} else { //如果不在map中则重新计算
maxValue = findMax(i+1, prices);
maxPrices[i] = maxValue;
}
//在map中更新后续数的个数
map.put(prices[i], map.get(prices[i]) - 1);
//如果某数的个数为0则移除
if(map.get(prices[i]) == 0) {
map.remove(prices[i]);
}
}
int max = 0;
for(int i = 0; i < prices.length; i++) {
max = Math.max(max, maxPrices[i] - prices[i]);
}
return max;
}
//找到start后的最大值
public int findMax(int start, int[] prices) {
int index1 = start, index2 = prices.length - 1;
while (index1 < index2) {
if (prices[index1] <= prices[index2]) index1++;
else index2--;
}
return prices[index2];
}
题解的做法是认为的最小值是被遍历过的数中的最小值,而不是直接找全局的最小值
算法实现:
public int maxProfit(int[] prices) {
int min = Integer.MAX_VALUE;
int max = 0;
for(int i = 0; i < prices.length; i++) {
if(prices[i] < min) { //如果当前价格比之前最低价格还低,则更新最低价格
min = prices[i];
} else { //如果当前价格比之前最低价格高,则计算当前价格与最低价格的差值,并更新最大值
max = Math.max(max, prices[i] - min);
}
}
return max;
}