最大子串和问题及其变形

今天英文面试的时候碰见的题目,倒是不难,就是稍微变形之后,一时没想起来。

n天股票价格的信息,只能买卖一次,问什么时候买卖利润最大。这道题真的是太过经典了,但是面试的时候虽然答出来了,但是解释的不是很好,一方面是因为英文面试所以不是很擅长表述,另外一方面解释的不够有逻辑性,认为面试官很多都知道的。可以如下解释:

  1. 这道题给形式化之后相当于找出一个i,j(i< j)使得nums[j]-nums[i]值最大
  2. 那么我们可以把原来的数组转化成为一个新的数组:差分数组。d[i] = nums[i+1]-nums[i],而 mi=ndi=nums[m+1]nums[n]
  3. 所以原问题就变成了,找出差值数组的最大子段和
  4. 这是一道动态规划可以做的题目
int f(vector<int> &nums){
    int mark = 0;
    int max_mark = 0;
    vector<int> d(nums.size()-1)
    for(int i=0;i<nums.size()-1;i++){
        d[i] = nums[i+1]-nums[i];
    }
    for(int i=0;i<d.size(),i++){
        if(mark+d[i]<0)
            continue;
        else
            mark += d[i];
        max_mark = max(max_mark,mark);
    }
    return max_mark;
}

我就是按照上面写法写的程序,不过面试官好像一直不是很明白其中的原理,因为用英文,所以我解释的也不是很清楚。下次可以注意发现面试官不是很理解的【尤其是欧美的面试官,一定不要跳跃太大
PS.后来跟舍友聊起来,舍友说转化成最大字段和的问题略麻烦了,还是直接用dp,储存一个当前情况下,最小低的点即可,其实跟最大字段和原理一样的,只不过不用另开一个数组了,降低了空间复杂度。解法如下:

int maxProfit(vector<int>& prices) {
    if(prices.size() == 0)
        return 0;
    int res = 0;
    int low_p = prices[0];
    for(int i=0;i<prices.size();i++){
        if(prices[i] < low_p){
            low_p = prices[i];
        }
        res = max(res,prices[i]-low_p);
    }
    return res;
}

然后面试官又问了一个变形,就是「如果这个人购买股票的资金量是一定的,还是只能买卖一次,那么如何购买才能使得利润最大?」当场想了一下没有想起来,回来之后跟舍友提起来,才明白这道题如何做。
即用log即可,还是转换成差分数组,但是这次不是相减了,而是相除,即找出最大字段乘积,且每个子段中每一项都是大于0的。【如果这道题不用差分来做的话,跟上面一题一样,都是保存一个最小的即可】
用后一种思路

int maxProfit(vector<int>& prices) {
    if(prices.size() == 0)
        return 0;
    int res = 1;
    int low_p = prices[0];
    for(int i=0;i<prices.size();i++){
        if(prices[i] < low_p){
            low_p = prices[i];
        }
        res = max(res,prices[i]/low_p);
    }
    return res;
}

用转化成最大字段和的问题,就是两两做除法,然后取log,然后再考虑一个最大字段和的问题。

double f(vector<int> &nums){
    double mark = 0;
    double max_mark = 0;
    vector<double> d(nums.size()-1)
    for(int i=0;i<nums.size()-1;i++){
        d[i] = log(nums[i+1]/nums[i]);
    }
    for(int i=0;i<d.size(),i++){
        if(mark+d[i]<0)
            continue;
        else
            mark += d[i];
        max_mark = max(max_mark,mark);
    }
    return exp(max_mark);
}

其实这个变形时非常简单的,但是当时却一直没有想出来,说明自己的应变能力还是得加强,另外一点就是面试的时候不要太紧张,好好分析题意。相信面试问到的问题都不难的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值