字节跳动面试--二面算法题复盘

题目描述:

股票最大收益问题
给定一段时间的某支股票价格集合,允许买卖各一次,求最大收益是多少?


例如

给定收入序列:[4,5,9,2,5,4,8]
为了满足要求,我们在第四天买入,第七天卖出,收益最大为6

 

结题思路:

暴力求解法的话,这里就不过多赘述了。博主当时脑子瓦特了,直接写了一波暴力解,复杂度当然就是O(n^2)了。面试官理所当然的很不满意,问我能不能优化。

沉思之后,我猛然发现这是一个典型的动态规划问题,动态规划的思想我就不说了,还请打开百度,移步其他博客。

针对此题,我做一个简单分析。一只股票,我们肯定要先买后卖(买入必定在卖出之前发生),也就是说我们收益最少也是0元(当天买入当天卖出)。所以我们只需要遍历一遍序列即可求的解。在遍历中,我们维持一个买入的最低价和一个当前最大收益,并且用遍历到的价格减去最低价来获得当前卖出可获得的最大收益的值,我们在这个收益值与历史最大收益值中取较大的一个即可。使用此办法之后,时间复杂度瞬间降到了O(n),面试官脸上也露出些许欣喜之色。

C++代码:

#include 
#include 

using namespace std;

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int GetMaxIncome(vector price){
	if(price.size() <= 1) return 0; //处理特殊情况
	int minPrice = price[0]; //维持一个最小值 
	int maxIncome = 0; //记录最大收益 
	for(int i = 1; i < price.size(); ++i){
		if(price[i] < minPrice){ //找到一个比当前最低价格还要低的价格,则替换之 
			minPrice = price[i];
			continue;
		}
		else{
			int currentIncome = price[i] - minPrice; //比较当前卖出的收益与之前记录的最大收益 
			if(currentIncome > maxIncome){
				maxIncome = currentIncome;
			}
		} 
	}
	return maxIncome; 
}

int main(int argc, char** argv) {
	vector price;
	price.push_back(4);
	price.push_back(5);
	price.push_back(9);
	price.push_back(2);
	price.push_back(5);
	price.push_back(4);
	price.push_back(8);
	//price.push_back(4);
	cout << GetMaxIncome(price);
	return 0;
}

后续:

你以为这就结束了?NO! NO! NO!

你以为面试官是那么好糊弄的?

于是,我立马收到了如下进阶版题目:

如果将买卖改为各两次,则最大收益是多少?
序列同上
在第一天买入,第三天卖出,第四天买入,第七天卖出,则收益为5+6。

 

当然了,迫于时间关系,面试官只要求我给出大概结题思路即可。

由于我比较菜,我说出了暴力解法,然后提了一嘴或许可以用二分法和递归结和来求解,但是具体操作我不会。

幸运的是面试官把我放过去了,我就迎来了字节标志性的连面,进入到紧张刺激的三面环节!

 

你可能感兴趣的:(面试复盘,字节跳动,面经,算法题)