大疆嵌入式软件笔试题2020.8.16

嵌入式软件岗,两道编程题都是动态规划。

第一题:求出数组中两个不重叠的子数组的最大和。

POJ 2479Maximum sum http://poj.org/problem?id=2479

#include 
#include 
using namespace std;

int helper(const vector& v)
{
    int n = v.size();
    vector left(n), right(n);
    //left[i]: 以i结尾的子数组最大和, right[j]: 以j开头的子数组最大和
    left[0] = v[0];
    for(int i = 1; i < n; i++) left[i] = max(left[i-1], 0) + v[i];
    right[n-1] = v[n-1];
    for(int j = n - 2; j >= 0; j--) right[j] = max(right[j+1], 0) + v[j];

    vector lmax(n), rmax(n);
    //lmax[i]: [0...i]中子数组的最大和, rmax[j]: [j...n-1]中子数组最大和
    lmax[0] = left[0];
    for(int i = 1; i < n; i++) lmax[i] = max(lmax[i-1], left[i]);
    rmax[n-1] = right[n-1];
    for(int j = n - 2; j >= 0; j--) rmax[j] = max(rmax[j+1], right[j]);

    int ans = -1e9;
    for(int i = 0; i < n - 1; i++)
    {
        ans = max(ans, lmax[i] + rmax[i+1]);
    }
    return ans;
}

int main()
{
    int q;
    scanf("%d", &q);
    for(int query = q; query > 0; query--)
    {
        int n;
        scanf("%d", &n);
        vector v(n);
        for(int i = 0; i < n; i++) scanf("%d", &v[i]);
        printf("%d\n", helper(v));
    }
    return 0;
}

一道可以采用相似思路去做的题目:

1156. 单字符重复子串的最大长度

如果字符串中的所有字符都相同,那么这个字符串是单字符重复的字符串。

给你一个字符串 text,你只能交换其中两个字符一次或者什么都不做,然后得到一些单字符重复的子串。返回其中最长的子串的长度。

 

示例 1:

输入:text = "ababa"
输出:3
示例 2:

输入:text = "aaabaaa"
输出:6
示例 3:

输入:text = "aaabbaaa"
输出:4
示例 4:

输入:text = "aaaaa"
输出:5
示例 5:

输入:text = "abcdef"
输出:1
 

提示:

1 <= text.length <= 20000
text 仅由小写英文字母组成。 

class Solution {
public:
    int maxRepOpt1(string text) {
        int n = text.size();
        int h[128] = {0};
        for(char c : text) h[c]++;
        vector s(n, 1), e(n, 1);
        //s[i]: 以 text[i] 开头的,只含有 text[i]的最长子串长度
        //e[i]: 以 text[i] 结尾的,只含有 text[i]的最长字串长度
        int ans = 1;
        for(int i = n - 1; i >= 0; i--)
        {
            int j = i + 1;
            while(j < n && text[j] == text[i]) j++;
            s[i] = j - i;
            //如果s[i] < h[text[i]],则一定可以移动一个相同字符接在后面
            ans = max(ans, s[i] < h[text[i]] ? s[i] + 1 : s[i]);
        }
        for(int i = 0; i < n; i++)
        {
            int j = i - 1;
            while(j >= 0 && text[j] == text[i]) j--;
            e[i] = i - j;
        }
        //如果 i 和 i+2 是相同的字符,中间隔着一个不同字符,那么一定可以把中间的这个字符换掉
        for(int i = 0; i < n - 2; i++)
        {
            if(text[i] != text[i+2] || text[i] == text[i+1]) continue;
            int sum = e[i] + s[i+2];
            if(sum == h[text[i]]) ans = max(ans, sum);
            else ans = max(ans, sum + 1);
        }
        return ans;
    }
};

 

第二题:类似1235. 规划兼职工作, 但是这一题还要输出使得利润最大的安排方式,考试的时候来不及想怎么得到安排方式,现在想应该可以从dp数组里获得安排的信息,但是没法验证这个想法对不对。根据leetcode 1235的用例测试了一下没有问题。

/*测试用例:第一行样例数t
每个样例,第一行任务数n
随后n行,每行四个数 id, start, end, profit
3
4
1 1 3 50
2 2 4 10
3 3 5 40
4 3 6 70
5
1 1 3 20
2 2 5 20
3 3 10 100
4 4 6 70
5 6 9 60
3
1 1 2 5
2 1 3 6
3 1 4 4
 
应该输出:
120,1,4
150,1,4,5
6,2
 */

#include 
using namespace std;

struct Node
{
    int id, s, e, p;
    Node(int i_ = 0, int s_ = 0, int e_ = 0, int p_ = 0): id(i_), s(s_), e(e_), p(p_){};
    bool operator < (const Node& other) const
    {
        return e < other.e;
    }
};

int main()
{
    int query;
    scanf("%d", &query);
    for(int q = query; q > 0; q--)
    {
        int n;
        scanf("%d", &n);
        vector all(n);
        for(int i = 0; i < n; i++)
        {
            scanf("%d%d%d%d", &all[i].id, &all[i].s, &all[i].e, &all[i].p);
        }
        sort(all.begin(), all.end());
        vector dp(n, 0);
        dp[0] = all[0].p;
        for(int i = 1; i < n; i++)
        {
            dp[i] = dp[i-1];
            auto it = upper_bound(all.begin(), all.begin() + i, Node(0, 0, all[i].s, 0));
            if(it != all.begin())
            {
                --it;
                dp[i] = max(dp[i], dp[it-all.begin()] + all[i].p);
            }
            else dp[i] = max(dp[i], all[i].p);
        }
        int i = n-1;
        vector ans;
        //根据dp数组恢复信息
        while(i >= 0)
        {
            if(i > 0 && dp[i] == dp[i-1]) i--;
            else
            {
                ans.push_back(i);
                auto it = upper_bound(all.begin(), all.begin() + i, Node(0, 0, all[i].s, 0));
                if(it != all.begin())
                {
                    --it;
                    i = it - all.begin();
                    continue;
                }
                else break;
            }
        }
        printf("%d", dp[n-1]);
        for(i = ans.size() - 1; i >= 0; i--) printf(",%d",all[ans[i]].id);
        printf("\n");
    }
    return 0;
}

 

你可能感兴趣的:(笔试)