牛客美团2024年春招第一场笔试【技术】解题

1.小美的平衡矩阵

小美拿到了一个n∗n的矩阵,其中每个元素是 0 或者 1。
小美认为一个矩形区域是完美的,当且仅当该区域内 0 的数量恰好等于 1 的数量。
现在,小美希望你回答有多少个i∗i的完美矩形区域。你需要回答1≤i≤n的所有答案

输出描述:
输出n行,第i行输出i*i的完美矩形区域的数量
例子:
输入例子:
4
1010
0101
1100
0011
输出例子:
0
7
0
1

1.1解题思路

1.1.1条件:

1.通过题目我们知道0和1相等才是完美矩形区域,所以我们只需求出矩阵的1的个数就可以了,这时我们可以想到前缀和(专门求矩阵的和)
2.第i行输出i*i的完美矩形区域的数量,得知到这个是确定矩阵边长大小,边长范围是1到n,边长奇数的一定不可能0和1相等

1.2思路

前缀和

  1. 构建前缀和矩阵:建立数组 S [ n ] [ m ] 来统计矩形 ( 1 , 1 ) 到(n,m) 中1 的数量左上矩阵,只用每次遍历矩形的左上定点,就可以确定整个矩形大小
  2. 然后统计该矩形中 01 的具体数量,判断是否相等,左上顶点 ( i , j ) 的矩阵,右下顶点即为 ( x , y ) ,其中 x = i + k − 1 , y = j + k − 1
  3. 字符 1 的数量即为 s [ x ] [ y ] − s [ i − 1 ] [ y ] − s [ x ] [ j − 1 ] + s [ i − 1 ] [ j − 1 ],字符 0 的数量为 k × k/ 2
    在这里插入图片描述
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static int n = 201;
    static int sum[][] = new int[n][n];
    static int a [][] = new int[n][n];
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        int row = in.nextInt();
        char[][] charArray = new char[row][];
        in.nextLine();
        // 循环读取每一行的字符串,并转换为字符数组
        for (int i = 0; i < row; i++) {
            String line = in.nextLine(); // 读取一行字符串
            charArray[i] =
                line.toCharArray(); // 将字符串转换为字符数组,并存储在二维数组中

        }
        for (int i = 0 ; i < row; i++) {
            for (int j = 0; j < row; j++) {
                a[i + 1][j + 1] = Integer.parseInt(Character.toString(charArray[i][j]));
                sum[i + 1][j + 1] = sum[i][j + 1] + sum[i + 1][j] + a[i + 1][j + 1] - sum[i][j];
            }
        }
        //k是边长
        for (int k = 1; k <= row; k++) {
            if ((k & 1) == 1) { // 当边长为奇数时
                System.out.println(0); // 字符 1的数量不可能等于字符 0的数量
                // 在循环中的话,这里应该是 continue; 
                continue;
            }
            int count = 0;
            for (int i = 1; i + k - 1 <= row ; i++ ) {
                for (int j = 1; j + k - 1 <= row ; j++) {
                    int x = i + k - 1;
                    int y = j + k - 1;
                    //核心部分
                    if (sum[x][y] - sum[i - 1][y] - sum[x][j - 1] + sum[i - 1][j - 1] ==
                            (k * k / 2)  ) {
                        count++;
                    }
                }
            }
            System.out.println(count);
        }

    }
}

2.小美的数组询问

小美拿到了一个由正整数组成的数组,但其中有一些元素是未知的(用 0 来表示)。
现在小美想知道,如果那些未知的元素在区间[𝑙,𝑟]范围内随机取值的话,数组所有元素之和的最小值和最大值分别是多少?
共有𝑞次询问。
输出描述:
输出q行,每行输出两个正整数,代表所有元素之和的最小值和最大值。
示例1
输入例子:
3 2
1 0 3
1 2
4 4
输出例子:
5 6
8 8
例子说明:
只有第二个元素是未知的。
第一次询问,数组最小的和是 1+1+3=5,最大的和是 1+2+3=6。
第二次询问,显然数组的元素和必然为 8。

2.1解题思路

2.1.1条件:
  1. 通过题目我们可以知道求最小值一定取的是l值,最大值取的是r值
  2. 确定好区间取法后,我们要知道未知数的个数也就是0的个数,最终求出最大和最小值

思路

语法基础: 循环结构

  1. 求0的个数count
  2. [ l , r ] 区间,最小值为 sum + count × l ,最大值为 sum + count × r。
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        //1.得到未知数的个数
        //2.得到l和r,l或者r*未知数的个数算出最大值最小值
        int number = in.nextInt();
        int query = in.nextInt();
        //算和的变量
        long sum = 0;
        long count = 0;
        for(int i = 0; i < number; i++){
            long temp = in.nextLong();
            sum+=temp;
            if(temp == 0){
                count++;
            }
        }
        for(int i = 0 ; i < query; i++){
            long l = in.nextLong();
            long r = in.nextLong();
            //min和max放到外面就提交不通过
            // long min = sum + (count * l);
            // long max = sum + (count * r);
            System.out.println((sum + (count * l) )+ " " + (sum + (count * r)));
        }
    }
}

3.小美的 MT

MT 是美团的缩写,因此小美很喜欢这两个字母。现在小美拿到了一个仅由大写字母组成字符串,她可以最多操作k次,每次可以修改任意一个字符。小美想知道,操作结束后最多共有多少个’M’和’T’字符?
输出描述:
输出操作结束后最多共有多少个’M’和’T’字符。
示例1
输入例子:
5 2
MTUAN
输出例子:
4
例子说明:
修改第三个和第五个字符,形成的字符串为 MTTAM,这样共有 4 个’M’和’T’。
语法基础: 顺序结构

3.1条件

  1. 找出字符串中 M 和 T 的字符数量count,答案即为count+q和n(字符串长度)的最小值。
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        int number = in.nextInt();
        int q = in.nextInt();
        int count = 0;
        in.nextLine();
        String s = in.nextLine();
        for(int i = 0 ; i < number; i++) {
            if(s.charAt(i) == 'M' || s.charAt(i) == 'T' ){
                count++;
            }
        }
        System.out.println(Math.min(number,count+q));
    }
}
  • 19
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值