1. 程式人生 > >ALDS1_1_D Maximum Profit

ALDS1_1_D Maximum Profit

題目連結

題目大意

                    給出一列數, 輸出最大值a_j-a_i (j>i)

題目的坑

                    看似很簡單, 直接兩層for迴圈就可以搞定了, 但這會超時。(因為我就是這麼做的..0.0)

典型的錯誤示例...

#include<iostream>
#include<stack>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;

int N;
int a[200005];
int main()
{
	scanf("%d", &N);
	for (int i = 0; i < N; i++)
		scanf("%d", &a[i]);
	int maxn = a[1] - a[0];
	
	for (int i = 0; i < N-1; i++)
	for (int j = i + 1; j < N; j++)
		maxn = max(maxn, a[j] - a[i]);

	cout << maxn << endl;
	return 0;
}

           如果用以上解法則時間複雜度約達到了 O(n^2), 肯定是過不去的。所以得進行優化, 那這裡怎麼進行優化呢?

 如果我們每找一次最大值, 並同時儲存當前的最小值, 就可以少一個for迴圈, 時間複雜度約為O(n), 可能這麼說還不是太明白. 

舉個例子: 假如這裡有一些數字 5,3,1,3,4,3 , 一開始我們取一個很小的數為最大值(比如maxn=-1e9),minn=5為最小值(只是一開始的預備處理, 後面會不斷更新的), 現在進入for迴圈開始找最大值, 首先是3-5和-1e9比較取最大值, 那麼現在的最大值是3-5(=-2), 同時儲存當前的最小值, 即再加上一條語句, minn=(3,minn), 則此時最小值為3, 那麼當進入下一次迴圈, 直接讓1-3 就可以了, 還會讓1-5嗎,這就沒意義了,因為3比5小, 減去越小的數字則結果會越大.

如果還不懂, 則要細細的品嚐程式碼~

#include<iostream>
#include<stack>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;

int N;
int a[200005];
int main()
{
	scanf("%d", &N);
	for (int i = 0; i < N; i++)
		scanf("%d", &a[i]);
	int maxn = a[1]-a[0];  //這裡我以a[1]-a[0]為初始的最大值
	int minn = a[0];
	for (int i = 1; i < N; i++)
	{
		maxn = max(maxn, a[i] - minn);  //a[i]減去當前最小值的結果 就是當前的最大值
		minn = min(a[i], minn);
	}
	cout << maxn << endl;
	return 0;
}

 如果你覺得這樣開這麼大的陣列去存資料浪費記憶體的話, 其實還可以再一次優化, 可以減少空間複雜度(親測可行^.^)

#include<iostream>
#include<stack>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;

int N;
int a;
int main()
{
	scanf("%d", &N);
	int maxn = (int)-1e9, minn;
	for (int i = 0; i < N; i++)
	{
		scanf("%d", &a);
		if (i == 0)     //i==0 主要就是設定第一個數字為最小值, 便直接進入下一次迴圈
		{
			minn = a;
			continue;
		}
		maxn = max(maxn, a - minn);  //a[i]減去當前最小值的結果 就是當前的最大值
		minn = min(a, minn);
	}
	cout << maxn << endl;
	return 0;
}