题目:买卖股票的最好时机

描述:假设你有一个数组,其中第 i个元素是股票在第 i天的价格。
你有一次买入和卖出的机会。(只有买入了股票以后才能卖出)。请你设计一个算法来计算可以获得的最大收益。

示例1:输入:[1,4,2],返回值:3

 

解法一:

思路分析:通读题目,思路很简单,可以直接采用暴力法解决问题,其余的方法就是在此基础上进行问题的优化。首先我们用变量i表示买入股票的时间,用变量j表示卖出股票的时间,所以prices[j] - prices[i]表示的就是股票的收益,通过不断循环找出其中的最大值即可。

具体实例分析:输入:[1,4,2],首先定义两个指针变量i和j,通过不断地计算max最大值来返回最终值的大小。

数值

1

4

2

第一轮指针

i

j

 

第一轮结果:max = 3

 

第二轮

i

 

j

第二轮结果:max = 3

 

第三轮

 

i

j

第三轮结果:max = 3

 

 

具体C++代码如下所示:

class Solution {
public:
    /**
     *
     * @param prices int整型vector
     * @return int整型
     */
    int maxProfit(vector<int>& prices) {
        int max = 0;//设置最大值变量
        int i,j;
        for(i = 0;i<prices.size();i++){//两层嵌套循环
            for(j = i+1;j<prices.size();j++){
                if(prices[j] - prices[i] > max){
                    max = prices[j] - prices[i];//通过循环判断最大值的结果
                }
            }
        }
        return max;//返回最大值
    }
};

其时间复杂度为O(N^2),因为是两层循环,所以不难得出时间复杂度为O(N^2),空间复杂度为O(1),在该算法中只使用了两个变量用于循环和日常开销。

解法二:

思路分析:上述暴力法中采用了两次遍历循环,会导致程序开销大,也可以采用一次比遍历循环,首先定义一个关于利润的容器profits,遍历整个数组,将利润存放在容器当中,逐个循环利润值,通过逐个判断利润值的大小,最终输出所谓的最大利润值。

具体实例分析:输入:[1,4,2],首先计算利润值分别为[3,-2],随后将进行利润值的判断,如果大于0,则进行累加,否则,将进行重新计数,加个if语句用于具体最大值判断。

具体C++代码如下所示:

class Solution {
public:
    /**
     *
     * @param prices int整型vector
     * @return int整型
     */
    int maxProfit(vector<int>& prices) {
        // write code here
        vector<int> profits;
        for(int i = 1; i < prices.size();++i){
            profits.push_back(prices[i] - prices[i-1]);//将差值存在容器中
        }
        int maxx = -1;//设置最大值
        int sum = -1;
        for(int i = 0;i < profits.size();++i){//将利润值进行循环判断
            if(sum > 0)
                sum += profits[i];
            else
                sum = profits[i];
            if(sum > maxx)
                maxx = sum;
        }
        return max(0,maxx);
    }
};

时间复杂度O(N)的计算分为两个部分,首先在预处理阶段耗时O(N),计算最大利润时采用了一次遍历,循环体内部指令开销为O(1),所以总体算法时间为O(N)。空间复杂度也为O(N)。