美团春招暑期实习笔试——20220312

本文介绍了三个编程题目:1.判断数字是否为幸运数字,2.计算序列中连续子序列乘积为正的数量,3.解决餐厅点菜问题以最大化顾客满意度。分别给出了Java代码实现,涉及条件判断、前缀和计算和递归等算法思想。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目一

  • 题目描述
    幸运数字至少满足以下两个特征中的一种
    1.数字是11的数倍
    2.数字中至少包含两个1
    小美现在给你若干的数字,希望你回答这个数字是不是幸运数字。

    输入描述:
    第一行一个数字n,表示小美有n组询问
    接下来每一行一个正整数表示小美询问的数字。
    数据保证1<=n<=500,每个询问的数字在【1,1e9】范围内

    样例输入:
    2
    22
    1234
    样例输出:
    yes
    no

  • Java代码

    import java.util.Scanner;
    public class Main{
    public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    int n=in.nextInt();
    while(in.hasNext()){
    int num=in.nextInt();
    if(num%110||oneCount(num)>=2){
    System.out.println(“yes”);
    }else{
    System.out.println(“no”);
    }
    }
    }
    private static int oneCount(int num) {
    int res=0;
    while (num>0){
    int remain=num%10;
    if(remain
    1)res++;
    num=num/10;
    }
    return res;
    }
    }

题目二

  • 题目描述
    小美现在有一个序列,序列中包含1和-1两种数字。小美现在想要知道,有多少个连续的子序列,序列中的数字乘积为正。

    输入描述:
    第一行一个正整数n,表示小美手中的序列长度。
    第二行n个空格隔开的数字,每个数字只能是1和-1中的一种。
    对于80%的数据保证1<=n<=500
    对于剩余的20%的数据保证1<=n<=5000

    输出描述:
    一行一个正整数表示有多少连续的子序列满足题目要求。

    样例输入:
    4
    1 1 -1 -1

    样例输出:
    6

  • 思路:先前缀和数组记录负数的个数,然后循环进行计算

  • Java代码

    import java.util.Scanner;
    public class Main{
    public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    int n = in.nextInt();
    in.nextLine();
    //将输入放入转换为数组
    String s = in.nextLine();
    String[] arrS = s.split(" ");
    int[] nums=new int[n];
    for (int i = 0; i < n; i++) {
    nums[i]=Integer.parseInt(arrS[i]);
    }
    //计算前缀和,所有负数
    int[] preNegative=new int[n+1];
    for (int i = 1; i <= n; i++) {
    if(nums[i-1]-1)preNegative[i]=preNegative[i-1]+1;
    else preNegative[i]=preNegative[i-1];
    }
    //双层循环计算一红有多少个序列
    int res=0;
    for (int i = 0; i < n; i++) {
    for (int j = i; j <n ; j++) {
    int count=preNegative[j+1]-preNegative[i];
    if(count%2
    0)res++;
    }
    }
    System.out.println(res);
    }
    }

题目三

  • 题目描述:点菜
    小美现在在厨房做饭。小美发现食材现在只够每种菜做一份。
    现在同一时刻(即不分先后顺序)来了n个顾客,每个顾客都有想两份要点的菜。只有当顾客吃到全部自己想要的菜的时候,顾客才会满意。
    现在你的任务是,合理地接取顾客的订单请求,尽可能让更多的顾客满意,并输出最多有多少顾客可以满意。

    输入描述:
    第一行两个正整数n,m
    n表明有多少顾客前来点菜,m表示小美现在能做的菜的编号范围在【1,m】,
    接下来的n行,每行两个数字,表明一名顾客的所点的两道菜的编号。
    前80%数据保证2<=n<=10,2<=m<=20
    剩余的80%数据保证2<=n<=20,2<=m<=40
    输出描述:
    一行一个正整数表示最多有多少顾客可以满意

    样例输入:
    3 4
    1 2
    2 3
    3 4

    样例输出:
    2
    解释:最佳方案满足第一个和第三个顾客

  • 思路:采用递归的方法

  • Java代码

    import java.util.Arrays;
    import java.util.Scanner;
    public class Main{
    public static int res=0;
    public static int[][] arr;
    public static int[] flag;
    public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    int n = in.nextInt();
    int m=in.nextInt();
    //存储顾客分别想要点的2道菜
    arr=new int[n][2];
    for (int i = 0; i < n; i++) {
    arr[i][0]=in.nextInt();
    arr[i][1]=in.nextInt();
    }
    //标记数字
    flag=new int[m+1];
    Arrays.fill(flag,1);
    int cnt=m/2; //最多可以满意的顾客数
    dfs(0,0,cnt,n);
    System.out.println(res);
    }

    //当前顾客数  已选择的人数
    private static void dfs(int guest, int sum,int cnt,int n) {
        if(sum<=cnt)res=Math.max(res,sum); //更新可选的最大的人数
        else return;
        for (int i = guest; i < n; i++) {
            int x1=arr[i][0],x2=arr[i][1];
            if(flag[x1]==0||flag[x2]==0)continue;
            flag[x1]--;flag[x2]--;
            //选择进行递归
            sum++;
            dfs(guest+1,sum,cnt,n);
            sum--;
            flag[x1]++;flag[x2]++;
        }
    }
    

    }

题目四

  • 题目描述
    小美现在打音游。这个音游的玩法是这样的:
    共有n个房间,小美初始拥有一个指针,指在一号房间。
    游戏共持续m秒,每秒会有一个房间产生炸弹,小美的指针不能在这个房间中
    每秒结束的瞬间,小美可以使用一次魔法,把指针切换到另一个房间中,该过程会消耗一个能量,
    你的任务是计算小美无伤通过音游消耗的最小的能量。
    保证第一秒炸弹不发生在一号房间中。

    输入描述:
    第一行两个正整数n,m,表示房间有n个,游戏持续m秒
    第二行m个正整数,每个正整数在1到n的范围内,第i个表示炸弹爆炸的房间

    样例输入:
    2 4
    2 1 1 2
    样例输出:
    2

    样例输入:
    3 10
    2 3 1 3 2 1 1 2 3 1
    样例输出:
    3

  • 笔者一开始做的时候用的是贪心算法,每次爆炸后用set集合记录爆炸及其之后的房间号,当记录到set的长度等于房间数n的时候再次爆炸,结果是部分样例通过,说明方法有误,代码如下

  • Java代码

    import java.util.HashSet;
    import java.util.Scanner;
    public class Main{
    public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    while (in.hasNext()){
    String s0 = in.nextLine();
    String[] s00 = s0.split(" “);
    int house=Integer.parseInt(s00[0]);
    int time=Integer.parseInt(s00[1]);
    String s = in.nextLine();
    String[] s1 = s.split(” ");
    //炸弹出现的数组
    int[] nums=new int[time];
    for (int i = 0; i < time; i++) {
    nums[i]=Integer.parseInt(s1[i]);
    }
    int res=0; //表示消耗的能量
    int currenthouse=1;
    HashSet set = new HashSet<>();
    for (int i = 0; i < time; i++) {
    if(currenthouse==nums[i]){ //房间要爆炸
    set.clear();
    set.add(nums[i]);//爆炸的加进去
    res++; //必须换房间,换的房间不知道
    currenthouse=-1;//暂且不确定去哪个
    }
    else if(currenthouse!=nums[i]&&set.size()<house-1){
    set.add(nums[i]);
    }
    else if(currenthouse!=nums[i]&&!set.contains(nums[i])){
    set.clear();
    set.add(nums[i]);//爆炸的加进去
    res++; //必须换房间,换的房间不知道
    currenthouse=-1;//暂且不确定去哪个
    }
    }
    System.out.println(res);
    }
    }
    }

  • 正确的思路是动态规划如下

    import java.util.Arrays;
    import java.util.Scanner;
    public class Main{
    public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    int n=in.nextInt(); //表示共n个房间
    int m=in.nextInt(); //表示游戏共持续m秒
    int[] bomb=new int[m+1];
    for (int i = 1; i <=m; i++) {
    bomb[i]=in.nextInt();
    }
    int[][] dp=new int[m+1][n+1]; //表示游戏持续到第i秒,小美指向j个房间
    for (int i = 0; i <=m; i++) {
    Arrays.fill(dp[i],Integer.MAX_VALUE-10000);
    }

        dp[1][1]=0;//初始,第一秒在第一个房间不消耗
        for (int i = 2; i <=m; i++) {
            for (int j = 1; j <=n; j++) {
                if(bomb[i]==j)continue;
                for (int k = 1; k <=n; k++) {
                    dp[i][j]=Math.min(dp[i-1][k]+(j==k?0:1),dp[i][j]);
                }
            }
    
        }
        int res=Integer.MAX_VALUE;
        for (int i = 1; i <=n; i++) {
            res=Math.min(res,dp[m][i]);
        }
        System.out.println(res);
    }
    

    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值