pdd笔试第三四题ac题解(nlgn)

第四题一开始一直是10% 最后一分钟马上放弃了 突然发现少了个条件 然后填上就a了

主要思路是离散化+滑动窗口

首先发现颜色数量有那么点点大 如果按照从c[i]进行遍历铁定超时 所以采用map进行一次离散化

同时建立一个vector数组的数组 vect[i]存的形式为a0 b0 a1 b1 a2 b2 a3,其中ax表示有连续 ax 个 i 颜_色 ,[放和谐] bx表示 ax- 1到 ax 之间 的 与i不同的颜 色的个数
发现是不是有些过于意识流 我来举一个例子
对于
1 12 3 1 12 3 1 12 3
这种输入通过map离散能将原输入变为
0 1 2 0 1 2 0 1 2
之后对于vect数组
vect[0] 1 2 1 2 1 代表首先连续出现了一个0 之后与下一个0距离为2 之后又连续出现了一个0 之后与下一个距离还为2 之后又连续出来了一个0
所以
vect[1]也是 1 2 1 2 1 简单分析便可知道 我们不用存储每个元素与开始或结束位置的距离
所以在本样例中 vect[0] = vect[1] = vect[2]
粗略分析一下时间复杂度 每次遍历到一个元素 至多会向整个vec数组中添加两个元素 一个向这个元素对应的位置添加与上个相同元素的间隔 一个向前一位元素添加连续出现的次数
之后在对每个颜色进行滑动窗口时
数组中每个元素至多被访问两遍
因此数组每个元素至多被遍历四遍
而离散的消耗是O(nlogk) k为元素的取值个数
针对题目要求k <= n
因此算法的总复杂度是O(nlogn)
很符合1e5的数据规模
至于如何在这种奇葩的数组中进行滑动窗口 我觉得还是比较好想的就不继续说了
本题数据应该挺水的O(n^2)的复杂度也能混过去

#include <iostream>
#include <map>
#include <vector>
#include <cstring>
#define maxn 100001
using namespace std;
int cnt = 0;
int asd[maxn];
int yuan[maxn];
vector<int>vec[maxn];
int ls[maxn];
int main() {
    memset(ls,-1,sizeof(ls));
    int n,k;
    cin >> n >> k;
    map<int, int>see;
    for(int i = 0; i < n; i++){
        int t;
        cin >> t;
        auto ite = see.find(t);
        if(ite == see.end()){
            see[t] = cnt++;
        }
        asd[i] = see[t];
    }
    int pre = asd[0],siz = 1;
    ls[asd[0]] = 0;
    for(int i = 1; i < n; i ++){
        if(pre != asd[i]){
            if(ls[asd[i]] != -1){
                //cout << asd[i] <<" " <<i - ls[asd[i]] - 1 << endl;
                vec[asd[i]].push_back(i - ls[asd[i]] - 1);
            }
            vec[pre].push_back(siz);
            ls[asd[i]] = i;
            //cout<<pre << " "<<siz<<endl;
            pre = asd[i];
            siz  = 1;
        }else{
            ls[asd[i]] = i;
            ++siz;
        }
    }
    vec[pre].push_back(siz);
    int maxx = 0;
    for (int i = 0; i < cnt; ++i) {
        vector<int>& e = vec[i];
        int siz = e.size();
        int r = 0;
        int p = 0;
        int temp = e[0];
        for(int j = 0; j < siz; j+=2){
            if(r < j){
                r = j;
                temp = e[j];
                p = 0;
            }
            while(p < k && r != siz-1){
                if(p + e[r+1] <= k){
                    temp += e[r+2];
                    p+=e[r+1];
                    r += 2;
                }else
                break;
            }
            if(temp > maxx)
            maxx = temp;
            if(r > j){
                p -= e[j+1];
                temp -= e[j]; 
            }
        }
    }
    cout << maxx;
}

第三题思路就很直观了 我觉得看看代码就能懂 就不分析了

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
int k[10];
int main(){
    int n,tb;
    cin >> n >> tb;
    string t;
    cin >> t;
    for(int i = 0; i < n; i++){
        ++k[t[i]-'0'];
    }
    int minn = 999999999;
    int c = -1;
    for(int i = 0; i < 10; i++){
        int temp = 0;
        int tc = tb - k[i];
        for(int j = 1; j < 10; j++){
            if(tc <= 0)
            break;
            if(i-j >= 0){
                int p = min(k[i-j],tc);
                tc -= p;
                temp += p*j;
            }
            if(tc == 0)
            break;
            if(i+j < 10){
                int p = min(k[i+j],tc);
                tc -= p;
                temp += p*j;
            }
            if(tc == 0)
            break;
        }
        //cout << temp << " " << i <<endl;
        if(minn > temp) {
            minn = temp;
            c = i;
        }
    }
    int b = tb -k[c];
    for(int i = 1; i < 10; i++){
        if(b <= 0)
        break;
        if(c + i  < 10){
            for(int j = 0; j <= n-1 && b > 0; j++){
                if(t[j] == '0'+c+i){
                    t[j] = '0'+c;
                    b--;
                }
            }
        }
        if(b <= 0)
        break;
        if(c - i  >= 0){
            for(int j = n-1; j >= 0 && b > 0; j--){
                if(t[j] == '0'+c-i){
                    t[j] = '0'+c;
                    b--;
                }
            }
        }

    }
    cout << t;
}
#拼多多笔试##拼多多##笔试题目#
全部评论
大佬tql
点赞 回复 分享
发布于 2020-04-12 18:18
好好写了写题解 应该能看懂了
点赞 回复 分享
发布于 2020-04-11 04:25
第四题看不懂。。。
点赞 回复 分享
发布于 2020-04-11 01:29
大佬tql
点赞 回复 分享
发布于 2020-04-10 23:57
求问大佬,第四题,你最后发现少了什么条件,然后就从10%到AC了?
点赞 回复 分享
发布于 2020-04-10 22:02
大佬 mark一下
点赞 回复 分享
发布于 2020-04-10 21:47
大佬tql
点赞 回复 分享
发布于 2020-04-10 21:43
楼主,题目三我思路和你是一致,就是后面换成新的数组的时候,我优先换c+i,然后换c-i。这样只过了60%。可是,你换值的时候,就只考虑c-i的情况,为啥呀。 我看你上面计算最小损失的时候,也是两头去的,
点赞 回复 分享
发布于 2020-04-10 21:29
大佬tql
点赞 回复 分享
发布于 2020-04-10 21:22

相关推荐

erer__:我也挺晚的,10月23号才开始投递。然后11月12号才有第一次面试。日常实习挺看运气的,要看有没有岗位。感觉到后面可能岗位会更少了,不过多投吧。加油
投了多少份简历才上岸
点赞 评论 收藏
分享
评论
2
16
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务