美团暑期实习

只留下了后两道编程题。。。 不过据说前两个编程题比较简单

编程题03 - 众数

具体题我就不抄了.. 大概意思是求滑动窗口(长度为k)内的所有最小众数(只有一个众数 直接输出, 有多个众数出现次数相同-> 输出最小的)


具体方案是维护这样一个数据结构:

  • hash: 维护窗口内每个元素的出现次数

  • vector<set<int>> A : 对于每个出现次数i而言 A[i]存放出现次数为i的所有元素

这样在进入窗口和弹出窗口的时候更新一下这两个就好了

void modify(vector<set<int>>& A, unordered_map<int, int>& hash, int val,  bool is_add)
{
    A[hash[val]].erase(val);
    if(is_add) hash[val]++;
    else hash[val]--;
    A[hash[val]].insert(val);
}

vector<int> solution(vector<int>& nums, int k)
{
    vector<int> res;
    unordered_map<int, int> hash;
    vector<set<int>> A(k + 1); // 出现次数为i的元素所在的集合
    for(int l = 0, r = 0, max_cnt = 0; r < nums.size(); r++)
    {
        modify(A, hash, nums[r], true);
        if(hash[nums[r]] > max_cnt) max_cnt = hash[nums[r]];
        if(l < r - k + 1)
        {
            modify(A, hash, nums[l++], false);
            if(A[max_cnt].empty()) max_cnt--;
        }
        if(r >= k - 1) res.push_back(*A[max_cnt].begin());
    }
    return res;
}

编程题04 - 树上DP

美团图论和dp是必考的 得了 这回考了个图论+dp的结合

具体题的意思: 给定一棵树,每一个节点有一个权重,选择其中某些节点,满足被选中的节点两两不相邻,求在所有的选择方案中,最大化被选择节点权值之和的情况下,被选择节点权值最小值尽可能大。

输入

第一行两个整数N和M,分别表示树的节点数和边数 第二行为N个整数,分别表示每个节点的权重 接下来M行,每行两个整数a和b,存在一条从a到b的边。

输出

输出两个整数,表示能选择的最大权值之和是多少,以及权值最小值是多少,用空格分割。

输入样例

输出样例


基础就是 树上一条边只能选一个节点, 求权值最大 可以说是树上DP的经典题了

这题比我做过的树上DP还要怪 我开始也没反应过来那个最大化被选择节点权值之和的情况下,被选择节点权值最小值尽可能大是啥意思

后来发现是在两个子节点权值一样 选哪个都可以的时候,选哪个权值大的child

剩下的建图和DFS(是的树上dp都是dfs写的)都是很经典的套路了

  • f[i, 0] 表示不选node[i]的最大方案

  • f[i, 1] 表示选node[i]的最大方案

Last updated