笔试面试辅导题(二)

107 阅读1分钟

股票买卖 III

image.png

//1次交易的话,第i天的最大收益需要找到前i-1天的min
#include <iostream>
using namespace std;

const int N = 1e5+10;
int n, p[N], g[N], f[N];

int main()
{
    cin>>n;
    for(int i = 1; i <= n; i ++) cin>>p[i];
    //g[i]是1-i中交易一次的max值
    for(int i = 2, minv = p[1]; i <= n; i ++)
    {
        g[i] = max(g[i-1], p[i] - minv);
        minv = min(minv, p[i]);
    }
    //f[i]是i-n中交易一次的max值
    for(int i = n - 1, maxv = p[n]; i >= 1; i --)
    {
        f[i] = max(f[i+1], maxv - p[i]);
        maxv = max(maxv, p[i]);
    }
    //遍历分界点
    int res = 0;
    for(int i = 2; i <= n; i ++) res = max(res, g[i] + f[i+1]);
    cout<<res<<endl;
    return 0;
}

1487.取硬币

完全背包问题是n*n复杂度: image.png

01从大到小,完全从小到大 image.png

//前n1个是01背包,后n2个是完全背包
#include <iostream>
using namespace std;
const int N = 100010, MOD = 1e9+7;

int n1, n2, m;
int f[N];
int main()
{
    cin>>n1>>n2>>m;
    f[0] = 1;
    for(int i = 1; i <= n1; i ++)
    {
        int p;
        cin>>p;
        for(int j = p; j <= m; j ++) f[j] = (f[j] + f[j-p]) % MOD;
    }
    for(int i = 1; i <= n2; i ++)
    {
        int p;
        cin>>p;
        for(int j = m; j>= p; j --) f[j] = (f[j] + f[j-p]) % MOD;
    }
    cout<<f[m]<<endl;
    return 0;
}

1488. 最短距离

image.png 普通做法要n*n复杂度,采用超级源点,向每一个商店连有向边,求s到所有点的单源最短路径,复杂度o(m)

image.png

1489. 田忌赛马

image.png

image.png

//不能赢的马只有平和输两种情况,输的话可以当作炮灰死得其所,让另一局赢
//贪心问题,一部分的解通过分析可以直接去掉
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 1010;
int n;
int a[N], b[N];

int judge(int x, int y)
{
    if(a[x] > b[y]) return 1;
    if(a[x] < b[y]) return -1;
    return 0;
}
int main()
{
    while(cin >> n, n)
    {
        for(int i = 0; i < n; i ++) cin>>a[i];
        for(int i = 0; i < n; i ++) cin>>b[i];
        
        //从大到小排序,只用分析最快和最慢的,因为去掉这两个马剩下的马里面还有最快和最慢的
        sort(a, a+n, greater<int>());
        sort(b, b+n, greater<int>());
        
        int f1 = 0, f2 = 0, s1 = n - 1, s2 = n - 1;
        int res = 0;
        while(f1 <= s1)//田的马小于国王的,分情况
        {
            if(judge(s1, s2) > 0) res ++, s1 --, s2 --;
            else if(judge(s1, s2) < 0) res += judge(s1, f2),s1 --, f2 ++;//如果要输,就打国王最快的
            else
            {
                if(judge(f1, f2) > 0) res ++, f1++, f2++;
                else res += judge(s1, f2), s1--, f2 ++;//剩下两种情况
            }
        }
        cout<< res * 200<<endl;
    }
    return 0;
}

77. 翻转单词顺序

/*
for(int i = 0, j = s.size() - 1; i < j; i++,j--) swap(i,j);反转整个字符串
*/
//要求o(n)时间o(1)空间,类似矩阵翻转的题,拆解,先翻转整个句子,再翻转单个单词
class Solution {
public:
    string reverseWords(string s) {
        reverse(s.begin(), s.end());
        //经典结构:新变量j找空格
        for(int i = 0; i < s.size(); i ++)
        {
            int j = i;
            while(j < s.size() && s[j] != ' ') j ++;
            reverse(s.begin() + i, s.begin() + j);
            i = j;
        }
        return s;
    }
};