【牛客】美团2024届秋招笔试第三场编程真题

1.平均数为k的最长连续子数组【有点难度,主要是这个思路是真没想起来】

题意理解:

        求最长连续子序列,该子序列满足平均值为k的条件

解题思路:

        1.双for循环遍历所有子串,但是超时了

        2.第二种思路, 给所有的元素-平均数k,问题就变成了最长连续子序列,和为0,所以呢?然后相等还是遍历所有子串,和之前没有什么不同了,时间复杂度还是过不去。

        3.第三种思路,借鉴大佬的思路,原来考的是前缀和+哈希表

                哈希表里面存的值是索引,需要注意累加和sum需要用long

                使用pre来记录前n个元素的和,map记录的是截止当前索引i下,元素和为cur

                其实本质思路是:

                        第i个元素的时候求和sum=a, 第j个元素的时候求和sum=a则说明

                       (i,j]区间的元素和为0,故此处长度为0的子串长度为: j-i

1.解题思路

import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Main solution=new Main();
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        int n = in.nextInt();
        int k = in.nextInt();
        int[] nums=new int[n];
        for(int i=0;i<n;i++){
            nums[i]=in.nextInt();
        }
        System.out.println(solution.compute(n,k,nums));
       
    }
    public int compute(int n,int k,int[] nums){
        //记录结果
        int maxLen=-1;
        //前i个数的和
        long pre=0;
        
        Map<Long,Integer> map=new HashMap<>();
        map.put(0L,0);
        for(int i=0;i<n;i++){
            //将avg=k的约束转换为sum=0
            long cur=pre+nums[i]-k;
            if(map.containsKey(cur)){
                maxLen=Math.max(maxLen,i+1-map.get(cur));
            }else{
                map.put(cur,i+1);
            }
            pre=cur;
        }
        
        return maxLen;
    }

   
}

2.复杂度分析

时间复杂度:O(n) for循环的存好

空间复杂度: O(2n) map的元素存储损耗

2.小球投盒【不难,但是可能出小问题】

题意理解:

        有一堆盒子,两种操作:

        操作1:往编号为i的元素中放一个球

        操作2:除编号i的元素放一个球

        操作到第几次时,所有盒子里都有小球

解题思路:

        1.用一个list模拟盒子,进行操作,放过球,则将对应元素n移除list, 当前仅当list为空时,所有盒子有小球

        2.考的是控制处理流程,不算难,但是容易超时

        几个超时问题:

        set.clear()会超时,但是set=new HashSet<>()不会,空间换时间的tips

1.解题

import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Main main = new Main();
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();
        int[][] opts = new int[m][2];
        for (int i = 0; i < m; i++) {
            opts[i][0] = in.nextInt();
            opts[i][1] = in.nextInt();
        }
        System.out.println(main.commpute(n, m, opts));

    }
    public int commpute(int box, int optNum, int[][] opts) {
        Set<Integer> set = new HashSet<>();
        for(int i=1;i<=box;i++) set.add(i);
        for(int i=1;i<=optNum;i++){
            int target=opts[i-1][1];
            //移除一个小球
            if(opts[i-1][0]==1&&set.contains(target)){
                set.remove( target);
            }else if(opts[i-1][0]==2&&(!set.isEmpty())){
                if(set.contains(target)){
                    set=new HashSet<>();
                    set.add(target);
                }else{
                    set.clear();
                
                }
                
            }
            if(set.isEmpty()){
                return i;
            }
        }
        return -1;
    }
}

2.复杂度分析

时间复杂度:O(n) for循环遍历的时间损耗

空间复杂度:O(2n) 盒子的空间损耗+opts操作存储的空间损耗

3.小红结账【简单题】

题意理解:

        共有n个账单,每次k个人吃饭,每次给小红的钱向上取整。

        其中小红的朋友共m个,其中同一个朋友可能参与多次聚餐,需计算,每个人总共需要转给小红的账单。而不是某一个账单需要转的钱!

解题思路:

        题目比较简单。使用payResult[m]维护结果,其中payResult[i]表示n个账单中,第i个朋友需给小红转的钱。

        遍历账单,计算avg平均数

        将平均数,加至指定朋友需付的钱中

        返回结果

        

1.解题

import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Main solution=new Main();
        Scanner in = new Scanner(System.in);
        
        int n = in.nextInt();
        int m = in.nextInt();
        int[][]  costItem=new int[n][2];
        String[] friends=new String[n];
        for(int i=0;i<n;i++){
            costItem[i][0]=in.nextInt();
            costItem[i][1]=in.nextInt();
            in.nextLine();
            friends[i]=in.nextLine();
        }
        long[] payResult=solution.compute(n,m,costItem,friends);
        for(long num:payResult){
            System.out.print(num+" ");
        }
        
    }
    public long[] compute(int n,int m,int[][] costItem,String[] friends){
        long[] payResult=new long[m];
        //遍历账单
        for(int i=0;i<n;i++){
            String[] num=friends[i].split(" ");
            // System.out.println("S:"+friends[i]+" | "+num.length);
            int payItem=(costItem[i][1]+num.length)/costItem[i][0];
            // System.out.println("Avg:"+payItem);
            for(int j=0;j<num.length;j++){
                int index=Integer.valueOf(num[j])-1;
                payResult[index]+=payItem;
            }
        }
        return payResult;
    }
}

2.复杂度分析

时间复杂度:O(O^2) 双for循环时间损耗

空间复杂度:O(2n) 账单存储损耗+结果数组存储损耗

4.小美的游戏【简单题】

题意理解

        有个n个元素的数组,将两个元素的ai,aj的乘积换成x,y的乘积,要使整个数组的总和尽可能的大。

解题思路

        为了使整个数组总和尽可能的大,就要使元素尽可能的大,最有效的一个方式如:

        比如获得两个元素: 4*5=20*1 将元素4+5换成20+1,

        所以,尽可能让两个大的元素相乘,并将其转换为1*乘积的两个元素,此时和最大

        1.对数组排序,大数在数组后面

        2.从后面进行遍历,每次将两个最大的数相乘,转换为1*乘积

        3.总是把1放在后面(i),乘积常在前面(i-1)的位置,方便继续两个最大值的相乘。

        4.最后求和        

1.解题

import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Main solution=new Main();
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int k = in.nextInt();
        long[] nums=new long[n];
        for(int i=0;i<n;i++){
            nums[i]=in.nextLong();
        }
        System.out.println(solution.compute(n,k,nums));
        
    }

    public long compute(int n,int k,long[] nums){
        long result=0;
        Arrays.sort(nums);
        for(int i=nums.length-1;i>=0;i--){
            if(k>0&&i>0){
                nums[i-1]=(long)(((nums[i]%(Math.pow(10,9)+7))*(nums[i-1]%(Math.pow(10,9)+7)))%(Math.pow(10,9)+7));
                nums[i]=1;
                k--;
            }
            result=(long)((result+nums[i])%(Math.pow(10,9)+7));
        }
        return result;
    }
}

2.复杂度分析

时间复杂度:O(n) for循环的时间损耗

空间复杂度:O(n) nums数组的空间损耗 

5.小美种果树 【简单题】

题意理解

        一个树成熟需要能量值z

        每天浇水+x

        每三天施肥+y

        求累计几天,能量值到达z

解题思路:        

        比较简单,在合适的位置累加x,y,当前且仅当sum>=z时,跳出循环,树成熟

1.解题

import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Main solution=new Main();
        Scanner in = new Scanner(System.in);
        int x = in.nextInt();
        int y = in.nextInt();
        int z = in.nextInt();
        System.out.println(solution.compute(x,y,z));
    }

    public int compute(int x,int y,int z){
        int sum=0;
        int i=0;
        while(sum<z){
            sum+=x;
            if(i%3==0){
                sum+=y;
            }
            i++;
        }
        return i;
    }
}

2.复杂度分析

时间复杂度:O(n) while循环的时间损耗

空间复杂度:O(1) 存储result的空间损耗

6.小美的数组重排【简单题】

题意理解

        两个数组,要求元素重排后,对应位置上的元素和满足[1,m]的条件限制

        能满足该条件则输出Yes,负责输出No

        共进行q次判断(询问)

解题思路

        对于数组a升序排列,数组b降序排列

        检查对应位置是否满足值在[1,m]的约束,符合Yes,否则No

        1.遍历q次询问

        2.判断

        3.输出结果

1.解题

import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Main main=new Main();
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        int q=in.nextInt();
        String[] result=new String[q];
        for(int i=0;i<q;i++){
            int n=in.nextInt();
            int m=in.nextInt();
            int[] a=new int[n];
            int[] b=new int[n];
            for(int j=0;j<n;j++){
                a[j]=in.nextInt();
            }
            for(int j=0;j<n;j++){
                b[j]=in.nextInt();
            }
            result[i]=main.compute(n,m,a,b);
        }
        for(String s:result){
            System.out.println(s);
        }
    }
    public String compute(int n,int m,int[] aArr,int[] bArr){
        Arrays.sort(aArr);
        Arrays.sort(bArr);
        for(int i=0;i<n;i++){
            if(aArr[i]+bArr[n-1-i]>m||aArr[i]+bArr[n-1-i]<1) return "No";
        }
        return "Yes";
    }
}

2.复杂度分析

时间复杂度:O(nlogn) sort的时间损耗

空间复杂度:O(n)  以为数组存储元素的空间损耗

7.判断ip地址是否合法【不难但易错】

题意理解:

        对于IP地址的判断

        1.是否合法地址

        2.是A\B\C哪类地址

解题思路

        题目比较好理解,但容易出错

         需要注意的地方:

        1.   address.split("\\.")

        当且仅当.在最后一位时:如1.2.3.4.  划分结果 1 2 3 4,但是其实是非法地址

        当且仅当.在第一位时:如  .1.2.3.4  划分结果为  “” 1 2 3 4,非法地址

        2.对于地址每部分,1.02.3.4   02是非法的表达

        3.对于非. 非数组的部分存在时,也是非法表达

1.解题

import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Main main=new Main();
        Scanner in = new Scanner(System.in);
        String address=in.nextLine();
        boolean flag=true;
        //元素检查
        for(int i=0;i<address.length();i++){
            if(address.charAt(i)!='.'&&(!Character.isDigit(address.charAt(i)))){
                flag=false;
                break;
            }
            if(address.charAt(i)=='.'&&i==address.length()-1){
                flag=false;
            }
        }
        //组成检查
        if(flag==true){
            String[] parts=address.split("\\.");
            if(parts.length!=4) flag=false;
            else{
                for(String part:parts){
                    if("".equals(part.trim())){
                        flag=false;
                        break;
                    }
                    if(part.length()>=2&&part.startsWith("0")){
                        flag=false;
                        break;
                    }
                }
            }
        }
        if(flag==false){
            System.out.println("invalid");
        }else{
            System.out.println(main.compute(address));
        }
    }

    public String compute(String addressStr){
        String result="";
        String[] address=addressStr.split("\\.");
        int part1=Integer.valueOf(address[0]);
        int part2=Integer.valueOf(address[1]);
        int part3=Integer.valueOf(address[2]);
        int part4=Integer.valueOf(address[3]);
        if(part1<0||part1>255||part2<0||part2>255||part3<0||part3>255||part4<0||part4>255) result="invalid";
        else if(part1<=125&&part1>=1){
            result="A_address";
        }else if(part1==126&&part2==0&&part3==0&&part4==0){
            result="A_address";
        }else if(part1<=191&&part1>=128){
            result="B_address";
        }else if(part1<=223&&part1>=192){
            result="C_address";
        }else {
            result="other";
        }
        return result;
    }
}

2.复杂度分析

时间复杂度:O(n) for循环时间损耗

空间复杂度:O(1) 结果result空间损耗

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值