牛客周赛 Round 34 题解 | DEFG

D小红的陡峭值

思路见注释

import java.util.*;
public class Main{
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt(),a[]=new int[n];
        for(int i=0;i<n;i++){
            a[i]=sc.nextInt();
        }
        int b[]=a.clone();
        Arrays.sort(b);
        if(b[n-1]==0){
            //说明全是0:
            for(int i=0;i<n-1;i++){
                a[i]=1;
            }
            a[n-1]=2;
        }
        boolean head=a[0]==0,tail=a[n-1]==0;
        //先处理所有0变成左边的数字或者右边的非零数字,方法就是正着溜一遍,反着溜一遍
        for(int i=0,j=-1;i<n;i++){
            if(a[i]!=0){
                j=a[i];
            }
            else if(j!=-1){
                a[i]=j;
            }
        }
        for(int i=n-1,j=-1;i>=0;i--){
            if(a[i]!=0){
                j=a[i];
            }
            else if(j!=-1){
                a[i]=j;
            }
        }
        //接下来验证所有数字的陡峭值是不是小于等于1
        long sum=0;
        for(int i=1;i<n;i++){
            sum+=Math.abs(a[i]-a[i-1]);
        }
        if(sum>1){
            System.out.println("-1");
            return;
        }
        if(sum==0){
            //此时只能修改首尾的数字,不然陡峭值至少是2了
            if(!head&&!tail){
                System.out.println("-1");
                return;
            }
            if(head){
                a[0]++;
            }
            else{
                a[n-1]++;
            }
        }
        for(int num:a){
            System.out.print(num+" ");
        }
    }
}

E小红的树形 dp

验证图是否为二分图即可

import java.util.*;
public class Main{
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        char c[]=sc.next().toCharArray();
        List<Integer> path[]=new List[n];
        for(int i=0;i<n;i++){
            path[i]=new ArrayList<>();
        }
        for(int i=0;i<n-1;i++){
            int u=sc.nextInt()-1,v=sc.nextInt()-1;
            path[u].add(v);
            path[v].add(u);
        }
        System.out.println(find(n,path,c));
    }
    static String find(int n,List<Integer> path[],char c[]){
        //先判断是否有非?的字符,有的话直接开始BFS,否则从0开始赋值并BFS
        boolean all=false;
        for(char ch:c){
            if(ch!='?'){
                all=true;
            }
        }
        if(!all){
            c[0]='p';
        }
        Queue<Integer> q=new LinkedList<>();
        boolean has[]=new boolean[n];
        for(int i=0;i<n;i++){
            if(c[i]!='?'){
                q.add(i);
                has[i]=true;
                while(!q.isEmpty()){
                    int a=q.poll();
                    for(int b:path[a]){
                        if(!has[b]){
                            if(c[a]==c[b]){
                                return "-1";
                            }
                            c[b]=(char)('p'+'d'-c[a]);
                            has[b]=true;
                            q.add(b);
                        }
                    }
                }
                break;
            }
        }
        return new String(c);
    }
}

F小红的矩阵构造

思路见注释:

import java.util.*;
public class Main{
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt(),m=sc.nextInt(),x=sc.nextInt(),ans[][]=new int[n][m];
        //x必定为偶数,那么x mod 4 的取值只能是0或者2
        if(x%4==0){
            //此时左上角四个都填上x/4,这样每行每列异或为0
            ans[0][0]=ans[0][1]=ans[1][0]=ans[1][1]=x/4;
        }
        else{
            //此时需要考虑x==2
            if(x==2){
                //只有在n和m等于2的时候可以得到{{1,0},{0,1}},但是题目要求m和n大于等于4,所以直接返回
                System.out.println("-1");
                return;
            }
            //可以先考虑左上的边长为3的正方形,分出6个数先保持异或和为0:
            //填充反对角6个位置为1
            ans[0][1]=ans[0][2]=ans[1][2]=ans[1][0]=ans[2][0]=ans[2][1]=1;
            //填充四角,依旧保持异或为0:
            ans[0][0]=ans[0][m-1]=ans[n-1][0]=ans[n-1][m-1]=(x-6)/4;
        }
        for(int a[]:ans){
            for(int b:a){
                System.out.print(b+" ");
            }
            System.out.println();
        }
    }
}

G小红的元素交换

思路: 1、首先如果没有颜色要求,那么就是找自环就行了,每个环内的交换次数就是环大小减1; 2、加上颜色,对于每个环,如果存在两种颜色,那么必定存在某俩可交换的位置是颜色相反的,否则二者所在的集体不构成环,,那么这样的环依旧可以环大小减1次交换到位; 3、对于某个环,如果其中的颜色单一,那么必然需要先从别的环内交换一个另外颜色的字符,之后进行环内交换,最后把换出去的那个再换回来,也就是比多了2步操作; 4、如何进一步减少次数呢?发现可以在纯色环之间进行交换,也就是纯白环可以先跟纯红环交换一个元素,再各自交换完后换回来,那么相当于只加了一个环的2,那么多余的交换次数,就是2倍的max(纯白环数,纯红环数) 5、还有啊,需要特判,非升序且全部纯色,无解

import java.util.*;
public class Main{
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt(),idx[]=new int[n];
        for(int i=0;i<n;i++){
            idx[sc.nextInt()-1]=i;
        }
        String s=sc.next();
        int ans=0,red=0,white=0;
        boolean visited[]=new boolean[n];
        for(int i=0;i<n;i++){
            if(!visited[i]){
                int count=1,p=i;
                boolean hasRed=s.charAt(i)=='R',hasWhite=s.charAt(i)=='W';
                visited[i]=true;
                while(!visited[idx[p]]){
                    count++;
                    p=idx[p];
                    visited[p]=true;
                    if(s.charAt(p)=='R'){
                        hasRed=true;
                    }
                    else{
                        hasWhite=true;
                    }
                }
                ans+=count-1;
                if(count!=1){
                    if(hasRed&&!hasWhite){
                        red++;
                    }
                    else if(!hasRed&&hasWhite){
                        white++;
                    }
                }
            }
        }
        if(ans!=0){
            //此时假如全是一种颜色,但是排列并不是有序的,那么无法交换,无解
            char c[]=s.toCharArray();
            Arrays.sort(c);
            if(c[0]==c[n-1]){
                System.out.println("-1");
                return;
            }
        }
        System.out.println(ans==0?0:ans+Math.max(red,white)*2);
    }
}

待续。。

全部评论

相关推荐

从大一开始就开始学习Java,一路走来真的不算容易,每次面试都被压力,不过这次终于达成了自己的一大心愿!时间线和面经:8.17-投递9.1-一面实习+项目拷打看门狗机制讲一下redis加锁解锁的本身操作是什么Lua脚本是干什么的udp和tcp讲一下流量控制讲一下令牌桶算法说一下大端和小端是什么线程和协程有什么区别怎么切换协程切换的时候具体做了什么对于程序来说,你刚才提到的保存和恢复现场,这个现场有哪些信息udp优势现在有一个客户端和服务端,要实现TCP的通信,我们的代码要怎么写服务器怎么感知有新的连接怎么处理多个客户端的请求连接TCP怎么处理粘包和分包现在有两个文件,然后每个文件都有一亿条URL,每个的长度都很长,要怎么快速查找这两个文件共有的URLHashmap底层说一下怎么尽量提升插入和查询的效率如果要查找快,查询快,还有解决非空的问题,怎么做LoadingCache了解吗手撕:堆排序9.4-二面部门的leader,超级压力面拷打实习+项目,被喷完全没东西类的加载到垃圾回收整个底层原理讲一遍类加载谁来执行类加载器是什么东西,和进程的关系Java虚拟机是什么东西,和进程的关系如果我们要执行hello&nbsp;world,那虚拟机干了什么呢谁把字节码翻译成机器码,操作时机是什么Java虚拟机是一个执行单元吗Java虚拟机和操作系统的关系到底什么,假如我是个完全不懂技术的人,举例说明让我明白一个操作系统有两个Java程序的话,有几个虚拟机有没有单独的JVM进程存在启动一个hello&nbsp;world编译的时候,有几个进程JVM什么时候启动比如执行一条Java命令的时候对应一个进程,然后这个JVM虚拟机到底是不是在这个进程里面,还是说要先启动一个JVM虚拟机的进程垃圾回收机制的时机能手动触发垃圾回收吗垃圾回收会抢占业务代码的CPU吗垃圾回收算法简单说说垃圾回收机制的stop&nbsp;the&nbsp;world存在于哪些时机垃圾回收中的计算Region的时候怎么和业务代码并行执行假如只有一个线程,怎么实现并行Java为什么要这么实现Java效率比C++慢很多,那为什么还要这样实现Java虚拟机到底是什么形式存在的说一下Java和C++的区别还有你对Java设计理念的理解无手撕面试结束的时候,我真的汗流浃背了,面试官还和我道歉,说他是故意压力面想看看我的反应的,还对我给予了高度评价:我当面试官这么多年,你是我见过最好的一个9.9-三面临时通知的加面,就问了三十分钟项目9.11-hr面问过往经历,未来计划,想从腾讯实习中得到什么?当场告知leader十分满意我,所以直接ochr面完一分钟官网流程变成录用评估中,30分钟后mt加微信告知offer正在审批9.15-offer这一次腾讯面试体验真的不错,每个面试官能感觉到专业能力很强,反馈很足,比起隔壁某节真是好太多以后就是鹅孝子了
三本咋了:当面试官这么多年你是我见过的最好的一个
你面试被问到过哪些不会的...
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

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