2019.9.11 小米笔试算法岗编程题 两个动归

1.最大连续子序列之和

时间限制:C/C++语言 1000MS;其他语言 3000MS
内存限制:C/C++语言 65536KB;其他语言 589824KB

题目描述:

给定K个整数的序列{ N1, N2, …, NK },其任意连续子序列可表示为{ Ni, Ni+1, …, Nj },其中 1 <= i <= j <= K。最大连续子序列是所有连续子序中元素和最大的一个, 例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{ 11, -4, 13 },最大和为20

输入:

一个整数数组

输出:

最大的和

样例:

输入:
1 2 3
输出:
6

思路:

动态规划经典例题。
dp[i]代表,使用了num[i]的子序列,最大和为多少。
既然dp[i]使用了num[i],那么dp[i+1]即为使用num[i+1],则这个子序列要么只有num[i+1]一个数,要么从上一个使用了num[i]的子序列接过来。(只要是非负数,怎么拿都不亏,负数才会出现问题)
∴dp[i] = max( dp[i-1]+num[i] , num[i])

代码:

#include <cstdio>
#include <string>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[100010];
int a[100010];
int n;
int split(string &s,int a[])
{
    int n = 0;
    int res = 0;
    int k = 1;
    s += ' ';
    for(int i=0;i<s.size();i++)
    {
        if(s[i]=='-')
        {
            k = -1;
            continue;
        }
        if('0'<=s[i] && s[i]<='9')
        {
            res = res*10 + s[i]-'0';
        }
        else
        {
            a[++n] = k*res;
            res = 0;
            k = 1;
        }
    }
    return n;
}
int main()
{
    string input;
    getline(cin,input);
    n = split(input,a);
    for(int i=1;i<=n;i++)
        dp[i] = max(0,a[i]);
    int max_num = 0;

    for(int i=1;i<=n;i++)
    {
        dp[i] = max(dp[i-1]+a[i],dp[i]);
        max_num = max(max_num,dp[i]);
    }
    cout<<max_num<<endl;
    return 0;
}


A了。难点在处理输入。

2.利润最大化

时间限制:C/C++语言 1000MS;其他语言 3000MS
内存限制:C/C++语言 65536KB;其他语言 589824KB

题目描述:

米兔是一个投资人,持有着小米的股票。股票价格每日都有波动,数组price代表了每日股票的具体价格,其中price[i]代表小米在第i天的股价。米兔最多可以进行两次交易(一个买进,卖出为一次交易)并且不能同时进行两次交易(必须在再次购买前出售掉之前的股票),米兔想知道他最多能够获得多少利润呢?

输入:

正整数序price,代表了股票价格。其中第i个数代表了第i天的价格。

输出:

两次交易后能获得的最大利润

样例:

输入:
2 1 5 0 2 3 1 4
输出:
8

思路:

枚举中间分隔,两头分别用前缀最小和后缀最大,最后再看看有没有只交易一轮的。其实一开始以为要开线段树来拿区间极值,写完线段树后发现用不上。这个算法效率不高,基本相当于暴力。

代码:

#include <cstdio>
#include <string>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXNUM = 100010;
int a[MAXNUM];
int n;
int split(string &s,int a[])
{
    int n = 0;
    int res = 0;
    int k = 1;
    s += ' ';
    for(int i=0;i<s.size();i++)
    {
        if(s[i]=='-')
        {
            k = -1;
            continue;
        }
        if('0'<=s[i] && s[i]<='9')
        {
            res = res*10 + s[i]-'0';
        }
        else
        {
            a[++n] = k*res;
            res = 0;
            k = 1;
        }
    }
    return n;
}
int dp[MAXNUM],min_v[MAXNUM],max_v[MAXNUM];
int main()
{
    string input;
    getline(cin,input);
    n = split(input,a);

    int max_num = 0;
    memset(min_v,0x3f,sizeof(min_v));
    for(int i=1;i<=n;i++)
        min_v[i] = min(a[i],min_v[i-1]);
    for(int i=n;i>=1;i--)
        max_v[i] = max(a[i],max_v[i+1]);


    for(int key=2;key<=n-2;key++)//枚举中间
    {
        int tempL = 0;
        for(int i=1;i<=key;i++)
        {
            tempL = max(tempL, a[i]-min_v[i]);
        }
        int tempR = 0;
        for(int i=n;i>=key+1;i--)
        {
            tempR = max(tempR, max_v[i]-a[i]);
        }
        max_num = max(max_num, tempL+tempR);
    }
    for(int i=1;i<=n;i++)
    {
        max_num = max(max_num, a[i]-min_v[i]);
    }
    cout<<max_num<<endl;
    return 0;
}

A了,不知道数据范围有多少,这个应该是O(n²)的。笑死我了,一开始写了4重for循环O(n^4)的,竟然能过77%。

	int max_num = 0;
    for(int i=1;i<=n-1;i++)
        for(int j=i+1;j<=n;j++)
            for(int k=j;k<=n;k++)
                for(int l=k+1;l<=n;l++)
                    max_num = max(max_num,a[j]-a[i] + a[l]-a[k]);
    cout<<max_num<<endl;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值