股票什麼時候買進什麼時候賣出收益最大----求最大子數組(算法導論第四章 4.1-3)

問題描述:某公司股票,給出n天內的股票價格,判斷什麼時候買入股票,什麼時候賣出股票收益最大

                                                     
0 1 2 3 4
價格 10 11 7 10 6
變化   1 -4 3 -4

問題轉換: 將變化看成一個數組即A[4]=[1,-4,3,-4], 求解A的最大子數組(即子數組各項和最大)

解法:

設數組爲A[n].(n個元素)

一、暴力求解(遍歷)

思路:遍歷所有子數組(時間爲

代碼:

#include<iostream>

using namespace std;

int* FindMaxSubarray(int* A,  int n)
{
	int * B=new int[3];
	B[0]=A[0]; //最大子數組和 
	B[1]=0;    //最大子數組最左邊元素下標
	B[2]=n-1;  //最大子數組最右邊元素下標
	for(int i=0;i<n;i++)
	{
	
		int sum=0;
		for(int j=i;j<n;j++)
			{
				sum+=A[j];
				if(sum>B[0])
				{
					B[0]=sum;
					B[1]=i;
					B[2]=j;
				}
			 } 
    }
    return B;
}

int main()
{
	int A[16]={13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
	int *B={0};
	B=FindMaxSubarray(A,16);
	cout<<"the maximum subarray is from A["<<B[1]<<"] to A["<<B[2]<<"]"<<endl;//結果爲A[7]到A[10] 
	cout<<"the maximum sum is "<<B[0]<<endl;//結果爲43 
	return 0;
}


二、分治策略(時間爲

思路:B[low..high]的一個最大子數組所處位置必然是以下三種情況之一:

             1完全位於A[low...mid]中

             2.完全位於A[mid+1,high]中

             3.跨越中點的子數組和中的最大者(找出形如A[i,mid]和A[mid+1,j]中的最大子數組,再合併)(時間爲

代碼:

#include<iostream>

using namespace std;

int* FindCross(int* A, int n,int m, int mid)
{
	int * B=new int[3];
	int left_max=A[mid];
	int sum1=left_max;
	int left_index=mid;
	for(int i=mid-1;i>=n;i--)
	{
		sum1+=A[i];
			if(sum1>left_max)
				{
					left_max=sum1;
					left_index=i;
				}		  
    }
    int right_max=A[mid+1];
	int sum2=right_max;
	int right_index=mid+1;
    for(int j=mid+2;j<=m;j++)
	{
		sum2+=A[j];
			if(sum2>right_max)
				{
					right_max=sum2;
					right_index=j;
				}
			  
    }
    B[0]=left_max+right_max;
    B[1]=left_index;
    B[2]=right_index;
    return B;
}

int* FindMaxSubarray(int* C,  int k, int t)
{
	
	if (k==t)
		{
			int * D_0=new int[3];
			D_0[0]=C[k];
			D_0[1]=D_0[2]=k;
			return D_0;
		}
	else
	{
		int * D_1=new int[3];//左半邊子數組的最大子數組 
		int * D_2=new int[3]; // 右半邊子數組的最大子數組 
		int * D_3=new int[3]; // 跨越中間元素所有子數組中的最大子數組
		int mid1=(k+t)/2;
		D_1=FindMaxSubarray(C, k, mid1);
		D_2=FindMaxSubarray(C, mid1+1, t);
		D_3=FindCross(C,k,t,mid1);
		if (D_1[0]>D_2[0] && D_1[0]>D_3[0])
			return D_1;
		else if (D_2[0]>D_1[0] && D_2[0]>D_3[0]) 
			return D_2;
		else
			return D_3;
	
	
	}
	
}

int main()
{
	int arr[16]={13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
	int *E={0};
	E=FindMaxSubarray(arr,0,15);
	cout<<"the maximum subarray is from arr["<<E[1]<<"] to arr["<<E[2]<<"]"<<endl;//結果爲arr[7]到arr[10] 
	cout<<"the maximum sum is "<<E[0]<<endl;//結果爲43 
	return 0;
}


三、非遞歸,線性時間的算法(時間爲)

思路:任何負的項不可能作爲最大子數組的起點;任何和爲負的子數組不可能是最大子數組的前綴;

代碼:

#include<iostream>

using namespace std;

int* FindMaxSubarray(int* A,  int k, int t)
{
	int *B= new int[3];
	B[0]=A[k];
	B[1]=k;
	B[2]=k;
	int sum=0;
	for(int i=k;i<=t;i++)
	{
		if (sum>0)
			sum+=A[i];	
		else
		{
			B[1]=i;
			sum=A[i];	
		}
		if (sum>B[0])
		{
			B[0]=sum;
			B[2]=i;
		}
				
	}
	return B;
}

int main()
{
	int arr[16]={13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
	int *E={0};
	E=FindMaxSubarray(arr,0,15);
	cout<<"the maximum subarray is from arr["<<E[1]<<"] to arr["<<E[2]<<"]"<<endl;//結果爲arr[7]到arr[10] 
	cout<<"the maximum sum is "<<E[0]<<endl;//結果爲43 
	return 0;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章