• 数组补全(秋季每日一题 10)


    给定一个 1 ∼ n 1∼n 1n 的排列 f 1 , f 2 , … , f n f_1,f_2,…,f_n f1,f2,,fn

    已知,对于 1 ≤ i ≤ n 1≤i≤n 1in f i ≠ i f_i≠i fi=i 始终成立。

    现在,因为一些原因,数组中的部分元素丢失了。

    请你将数组丢失的部分补全,要求数组在补全后仍然是一个 1 ∼ n 1∼n 1n 的排列,并且对于 1 ≤ i ≤ n 1≤i≤n 1in f i ≠ i f_i≠i fi=i 均成立。

    输入格式
    第一行包含整数 T T T,表示共有 T T T 组测试数据。

    每组数据第一行包含一个整数 n n n

    第二行包含 n n n 个整数 f 1 , f 2 , … , f n f_1,f_2,…,f_n f1,f2,,fn。如果 f i = 0 f_i=0 fi=0,则表示 f i f_i fi 已经丢失,需要补全。

    输出格式
    每组数据一行,输出补全后的 f f f 数组,整数之间空格隔开。

    如果方案不唯一,则输出任意合理方案即可。

    数据范围
    1 ≤ T ≤ 100 , 1≤T≤100, 1T100
    2 ≤ n ≤ 2 × 1 0 5 , 2≤n≤2×10^5, 2n2×105
    0 ≤ f i ≤ n , 0≤f_i≤n, 0fin至少两个 f i f_i fi 0 0 0
    同一测试点内所有 n n n 的和不超过 2 × 1 0 5 2×10^5 2×105
    数据保证有解。

    输入样例:

    3
    5
    5 0 0 2 4
    7
    7 0 0 1 4 0 6
    7
    7 4 0 3 0 5 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    输出样例:

    5 3 1 2 4
    7 3 2 1 4 5 6
    7 4 2 3 6 5 1
    
    • 1
    • 2
    • 3

    1. 记录孤立点
    2. 将孤立点插入任意一个开环中
    3. 将开环闭合
    4. 如何没有一个开环,则将孤立点集自成环
    #include
    #include
    #include
    
    using namespace std;
    
    const int N = 200010;
    
    int n;
    int pre[N], ne[N];
    bool st[N]; // 标记孤立点
    
    int main(){
        
        int t;
        scanf("%d", &t);
        
        while(t--){
            
            scanf("%d", &n);
            memset(ne, 0, 4*(n+1));
            memset(pre, 0, 4*(n+1));
            memset(st, 0, n+1); // 孤立点
            
            for(int i = 1; i <= n; i++) scanf("%d", &ne[i]), pre[ne[i]] = i;
            
            vector<int> v;
            for(int i = 1; i <= n; i++)
                if(!ne[i] && !pre[i]){ 
                    v.push_back(i);
                    st[i] = true;
                }
                
            bool flag = false;
            for(int i = 1; i <= n; i++){
                if(!st[i] && ne[i] && !pre[i]){ // 开环的头节点
                    
                    int u = ne[i]; // 尾
                    while(ne[u]) u = ne[u];
                    
                    if(!flag){
                        for(int j = 0; j < v.size(); j++){
                            
                            ne[u] = v[j];
                            u = ne[u];
                        }
                        flag = true;
                    }
                    
                    ne[u] = i;  // 连成环
                }
            }
            
            int hh = 0, tt = 0;
            if(!flag){  // 如过孤立点没有被插入任何一个开环,则他们自己成环
                
                for(int i = 0; i < v.size(); i++)
                    if(!hh && !tt) hh = tt = v[i];
                    else ne[tt] = v[i], tt = v[i];
                
                ne[tt] = hh;
            }
            
            for(int i = 1; i <= n; i++) printf("%d ", ne[i]);
            puts("");
        }
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
  • 相关阅读:
    ThreadLocal
    RCLane: Relay Chain Prediction for LaneDetection
    python-web开发环境准备
    diffusers-Tasks
    vellum 学习03 10/7 (知识补)
    bert ranking listwise demo
    bert入门
    【Qt之QMetaType】使用
    golang面试题:字符串转成byte数组,会发生内存拷贝吗?
    基于javaweb的疫情物业系统(java+ssm+vue+elementui+mysql)
  • 原文地址:https://blog.csdn.net/qq_46456049/article/details/127136990