股票买进卖出问题—百度实习招聘面试题

   2014年百度暑期实习招聘面试出现这个问题,其实是算法导论中讲解分治算法的一道题目。

问题:在某时刻买进某公司的股票,并在之后某个日期将其抛售,如何使得利益最大化,即卖出的价格和买进的价格之差最大。

分析:不妨用a[0] a[1] ...a[N]表示N+1天的股票价格,那么问题就是找到两点i和j使得a[j]-a[i]最大。

     a[j]-a[i]=a[j]-a[j-1]+a[j-1]-a[j-2]+a[j-2]+...+a[i+1]-a[i]=(a[j]-a[j-1])+(a[j-1]-a[j-2])+....+(a[i+1]-a[i])

所以求解a[j]-a[i]问题转换为:先求出当天股票价格与前一天股票价格的差,用b[1]....b[N]表示,b[1]为a[1]-a[0]即第1天的股票价格与第0天股票价格只差。

求解数组b[1]...b[N]最大子数组和。

1.分治算法

最大子数组的和一定是三种情况中的某一种,b[low....high],low为中间位置。

(1) 完全位于子数组b[low..mid]中,因此low<=i<=j<=mid

(2)完全位于子数组b[mid+1..high]中,因此mid+1<=i<=j<=high

(3)跨越中点

这样可以把原问题分解成两个小的子问题。

1.分治算法求解代码

 

#include "stdafx.h"
#include<limits>
#include<iostream>
#include<vector>
using namespace std;

struct Node
{
	int sum;
	int left;
	int right;
};
Node Find_Cross_Max(vector<int> a,int low,int mid,int high);
Node Find_Max(vector<int> a,int low,int high);
int _tmain(int argc, _TCHAR* argv[])
{
	vector<int>a;
	int x;
	char s;
	int tmp=0;
	while((cin>>x)&&(cin.get(s)))
	{
		a.push_back(x-tmp);
		tmp=x;
		if(s=='\n')
			break;
	}
	int N=a.size()-1;

	Node n;
	n=Find_Max(a,1,N);
	cout<<n.left<<" "<<n.right<<" "<<n.sum<<endl;
	return 0;
}
//分治算法求解最大子数组的和
Node Find_Cross_Max(vector<int>a,int low,int mid,int high)
{
	int left_sum=numeric_limits<int>::min();
	int left_max,right_max;
	int sum=0;
	for(int i=mid;i>=low;i--)
	{
		sum+=a[i];
		if(sum>left_sum)
		{
			left_sum=sum;
			left_max=i;
		}
	}
	int right_sum=numeric_limits<int>::min();
	sum=0;
	for(int i=mid+1;i<=high;i++)
	{
		sum+=a[i];
		if(sum>right_sum)
		{
			right_sum=sum;
			right_max=i;
		}
	}
	Node n;
	n.left=left_max;
	n.right=right_max;
	n.sum=left_sum+right_sum;
	return n;
}
Node Find_Max(vector<int>a,int low,int high)
{
	Node mid_n,left_n,right_n;
	if(low==high)
	{
		mid_n.left=low;
		mid_n.right=high;
		mid_n.sum=a[low];
		return mid_n;
	}
	else
	{
		int mid=(low+high)/2;
		left_n=Find_Max(a,low,mid);
		right_n=Find_Max(a,mid+1,high);
		mid_n=Find_Cross_Max(a,low,mid,high);
		if(left_n.sum>right_n.sum && left_n.sum>mid_n.sum)
			return left_n;
		else if(mid_n.sum>left_n.sum && mid_n.sum>right_n.sum)
			return mid_n;
		else
			return right_n;
	}
}

方法2:

        int max=a[0];
	int sum=0;
	int tm=0,left=0;
	int right;
	for(int i=0;i<7;i++)
	{
		sum+=a[i];
		if(sum>max)
		{
			right=i;
			left=tm;
			max=sum;
		}
		if(sum<0)
		{
			tm=i+1;
			sum=0;
		}
	}
	cout<<left<<" "<<right<<" "<<max;


 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值