本文參考自《劍指offer》一書,代碼采用Java語言。
題目
假設把某股票的價格按照時間先后順序存儲在數組中,請問買賣交易該股票可能獲得的利潤是多少?例如一只股票在某些時間節點的價格為{9, 11, 8, 5,7, 12, 16, 14}。如果我們能在價格為5的時候買入並在價格為16時賣出,則能收獲最大的利潤11。
思路
遍歷每一個數字,並保存之前最小的數字,兩者差最大即為最大利潤。
值得注意的是,我自己一開始寫的代碼是默認不能虧本(即可以不買入賣出,利潤不能為負數),所以比較簡單;但如果可以虧本,最大利潤指的是最小的虧損,那么要注意最小數字不能是最后一個。在下面的代碼中可以注意比較兩種情況的差別。可以考慮的例子如 { 16, 11, 7, 4, 2, 1 }
測試算例
1.功能測試(數組遞增/遞減/無序)
2.特殊測試(null,空數組)
3.邊界值測試(數組僅兩個數字)
Java代碼
//題目:假設把某股票的價格按照時間先后順序存儲在數組中,請問買賣交易該股
//票可能獲得的利潤是多少?例如一只股票在某些時間節點的價格為{9, 11, 8, 5,
//7, 12, 16, 14}。如果我們能在價格為5的時候買入並在價格為16時賣出,則能
//收獲最大的利潤11。
public class MaximalProfit {
public static int MaxDiff(int[] arr) {
if(arr==null || arr.length<2)
return -1; //error
int min=arr[0];
//最大利潤可以是負數,只要虧損最小就行
int maxDiff=arr[1]-min;
for(int i=1;i<arr.length;i++) {
if(arr[i-1]<min) //保存“之前”最小數字
min=arr[i-1];
if(arr[i]-min>maxDiff)
maxDiff=arr[i]-min;
}
//默認不能虧本,代碼簡單,上面復雜的代碼注意細節
// int maxDiff=0;
// for(int i=1;i<arr.length;i++) {
// if(arr[i]<min)
// min=arr[i];
// else if(arr[i]-min>maxDiff)
// maxDiff=arr[i]-min;
// }
return maxDiff;
}
//簡單快速測試下
public static void main(String[] args) {
int[] arr1=null;
System.out.println(MaxDiff(arr1)==-1);
int[] arr2={ };
System.out.println(MaxDiff(arr2)==-1);
int[] arr3={ 16, 16, 16, 16, 16 };
System.out.println(MaxDiff(arr3)==0);
int[] arr4={ 1, 2, 4, 7, 11, 16 };
System.out.println(MaxDiff(arr4)==15);
int[] arr5={ 16, 11, 7, 4, 2, 1 };
System.out.println(MaxDiff(arr5)==-1);
int[] arr6={ 9, 11, 5, 7, 16, 1, 4, 2 };
System.out.println(MaxDiff(arr6)==11);
int[] arr7={ 2,4};
System.out.println(MaxDiff(arr7)==2);
int[] arr8={ 4,2};
System.out.println(MaxDiff(arr8)==-2);
}
}
true true true true true true true true
收獲
1.蠻力法時間復雜度為O(n^2),肯定不對。我們從頭到尾遍歷,確定規律。可以發現找出之前的最小值即可。
