剑指 Offer 63. 股票的最大利润(121. 买卖股票的最佳时机)
题目:
思路:
【0】核心思路:本质上就是求一个差的最大值,所以用一个数值存储结果,一个数值存储已经遍历的的价格的最小值,然后基本就可以得出结果。
【1】思路一:暴力破解,利用两次循环,计算所有数值的差值,取出最大值【但是这种耗时,而且计算次数多】
【2】思路二:贪心算法,又可以说是双指针,因为本质上是要用到两个数值【result 和 min_price】,其中min_price为已遍历过的价格的最小值【这样可以确保后面的价格与最小值的差值是最大的】。
【3】思路三:转化为最大子序和,因为分析过后发现两者的结果是一致的。
代码展示:
public class Offer { //思路一:正常情况肯定是考虑暴力破解 //时间 244 ms 击败 5.57% //内存 41.2 MB 击败 63.92% public static int Method1(int[] prices){ if (prices == null || prices.length == 0) { return 0; } int result = 0; int tem_i,tem_j; for (int i = 0; i < prices.length-1; i++ ){ tem_i = prices[i]; for (int j = i+1; j< prices.length;j++){ tem_j = prices[j]; result = Math.max(result,(tem_j - tem_i)); } } return result; } //思路二:利用贪心算法 //时间 2 ms 击败 25.87% //内存 41.3 MB 击败 58.68% public static int Method2(int[] prices){ if (prices == null || prices.length == 0) { return 0; } int result = 0; for (int i = 1; i < prices.length; i++ ){ //保证得到的利润是最大的 result = Math.max(result,(prices[i]-prices[i-1])); //这里便是贪心的体现,保持最小值与后面的数进行计算 prices[i] = Math.min(prices[i],prices[i-1]); } return result; } // 思路三:参照最大子序和 // 假设数组的值是[a,b,c,d,e,f],我们用数组的前一个值减去后一个值,得到的新数组如下 [b-a,c-b,d-c,e-d,f-e] // 如[7,1,5,3,6,4] 则会变为 [-6,4,-2,3,-2] ,而我们所求的便是其中的最大子序和也就是[4,-2,3]这部分 // 时间 1 ms 击败 54.56% // 内存 41.4 MB 击败 51.45% public static int Method3(int[] prices){ if (prices == null || prices.length == 0) { return 0; } int length = prices.length; int cur = 0; int max = cur; for (int i = 1; i < length; i++) { cur = Math.max(cur, 0) + prices[i] - prices[i - 1]; //记录最大值 max = Math.max(max, cur); } return max; } }