第十五届蓝桥杯模拟赛第一期

第一题 最小的十六进制(答案:2730)

问题描述
  请找到一个大于 2022 的最小数,这个数转换成十六进制之后,所有的数位(不含前导 0)都为字母(A 到 F)。
  请将这个数的十进制形式作为答案提交。   

思路分析:2022对应的十六进制是7e6,那么题目的意思是想要所有数位最小而且不含前导0都为字母,仔细一想只有aaa了

public class lianxi {
public static void main(String[] args) {
     int i = Integer.parseInt("aaa",16);
     System.out.println(i);
   }
}

那要是你想不到是aaa的话,那就只能枚举,下面贴出代码:

import java.util.Scanner;

public class lianxi {
   public static void main(String[] args) {
      Scanner scanner = new Scanner(System.in);
      int n = 2022;
      boolean visit = true;
      while (true) {
         visit = true;
         String s = Integer.toString(n, 16);
         for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if ('0' <= c && c <= '9') {
               visit = false;
               break;
            }
         }
         if (visit == true) {
            System.out.println(s);
            System.out.println(n);
            break;
         }
         n++;
      }
   }
}

第二题 Excel的列(答案:BYT)

问题描述
  在 Excel 中,列的名称使用英文字母的组合。前 26 列用一个字母,依次为 A 到 Z,接下来 26*26 列使用两个字母的组合,依次为 AA 到 ZZ。
  请问第 2022 列的名称是什么?

思路分析:

方法一:可以使用excel工具,将其整理出来

方法二:

public class lianxi {
   public static void main(String[] args)  {
      int cnt = 702;
      for (int i = 1; i <= 26; i++) {
         for (int j = 1; j <= 26; j++) {
            for (int k = 1; k <= 26; k++) {
               cnt++;
               if (cnt == 2022) {
                  char a = (char) (i - 1 + 'A');
                  char b = (char) (j - 1 + 'A');
                  char c = (char) (k - 1 + 'A');
                  System.out.print(a + " " + b + " " + c);
                  break;
               }
            }
         }
      }
   }
}

第三题 相等日期(答案:70910)
问题描述

        对于一个日期,我们可以计算出年份的各个数位上的数字之和,也可以分别计算月和日的各位数字之和。请问从 1900 年 1 月 1 日至 9999 年 12 月 31 日,总共有多少天,年份的数位数字之和等于月的数位数字之和加日的数位数字之和。
        例如,2022年11月13日满足要求,因为 2+0+2+2=(1+1)+(1+3) 。
        请提交满足条件的日期的总数量。

思路分析:

方法一:使用循环,符合条件的计数,注意过程中闰年的判断


   public class lianxi {
      static int[] w = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};//这里把0索引位置的值设成0,目的是方便后面的输出
      static int y = 1900, m = 1, d = 1;
      public static void main(String[] args) {
         int ans = 0;
         while (y != 9999 || m != 12 | d != 31) {
            if (y % 400 == 0 || (y % 4 == 0 && y % 100 != 0)) w[2] = 29;//判断闰年
            else w[2] = 28;
            if (check()) ans++;
            d++;
            if (d > w[m]) {
               m++;
               d = 1;
            }
            if (m > 12) {
               m = 1;
               y++;
            }
         }
         if (check()) ans++;
         System.out.println(ans);
      }

      static boolean check() {
         int ans = 0;
         int sum = 0;
         // 计算年的和
         int a = y;
         while (a > 0) {
            ans += a % 10;
            a /= 10;
         }
         int b = m;
         int c = d;
         while (b > 0) {
            sum += b % 10;
            b /= 10;
         }
         while (c > 0) {
            sum += c % 10;
            c /= 10;
         }
         return ans==sum;
      }
   }


方法二:在Java中,LocalDate 是一个来自 java.time 包中的类,用于表示没有时区的日期。这个类提供了一系列方法来操作日期,例如获取日期的年、月和日,以及增加或减少日期等。不懂的小伙伴可以去搜索一下这个LocalDate 类的详细用法,在今后碰到类似的题目可以都用这个类。

import java.time.LocalDate;

public class lianxi {
   public static void main(String[] args) {
      LocalDate date1 = LocalDate.of(1900, 1, 1);
      LocalDate date2 = LocalDate.of(9999, 12, 31);
      int count = 0;
      while(!date1.equals(date2)){
         int year = date1.getYear();
         int month = date1.getMonthValue();
         int day = date1.getDayOfMonth();
         int sum1 = 0;
         int sum2 = 0;
         int sum3 = 0;
         while(year != 0){
            sum1 += year % 10;
            year /= 10;
         }
         while(month != 0){
            sum2 += month % 10;
            month /= 10;
         }
         while(day != 0){
            sum3 += day % 10;
            day /= 10;
         }
         if(sum1 == sum2 + sum3){
            count++;
         }
         date1 = date1.plusDays(1);
      }
      System.out.println(count);
   }
}

 第四题 多少种取法(答案:189)


问题描述
  小蓝有 30 个数,分别为:99, 22, 51, 63, 72, 61, 20, 88, 40, 21, 63, 30, 11, 18, 99, 12, 93, 16, 7, 53, 64, 9, 28, 84, 34, 96, 52, 82, 51, 77 。
  小蓝可以在这些数中取出两个序号不同的数,共有 30*29/2=435 种取法。
  请问这 435 种取法中,有多少种取法取出的两个数的乘积大于等于 2022 。

思路分析:数据量小,暴力枚举即可

public class lianxi {
   public static void main(String[] args) {
      int ans = 0;
      int[] nums = {99, 22, 51, 63, 72, 61, 20, 88, 40, 21, 63, 30, 11, 18, 99, 12, 93, 16, 7, 53, 64, 9, 28, 84, 34, 96, 52, 82, 51, 77};
      for (int i = 0; i < nums.length - 1; i++) {
         for (int j = i + 1; j < nums.length; j++) {
            if (nums[i]*nums[j]>=2022){
               ans++;
            }
         }
      }
      System.out.println(ans);
   }
}

第五题 最大连通分块(答案:148)

问题描述
  小蓝有一个 30 行 60 列的数字矩阵,矩阵中的每个数都是 0 或 1 。
  110010000011111110101001001001101010111011011011101001111110
  010000000001010001101100000010010110001111100010101100011110
  001011101000100011111111111010000010010101010111001000010100
  101100001101011101101011011001000110111111010000000110110000
  010101100100010000111000100111100110001110111101010011001011
  010011011010011110111101111001001001010111110001101000100011
  101001011000110100001101011000000110110110100100110111101011
  101111000000101000111001100010110000100110001001000101011001
  001110111010001011110000001111100001010101001110011010101110
  001010101000110001011111001010111111100110000011011111101010
  011111100011001110100101001011110011000101011000100111001011
  011010001101011110011011111010111110010100101000110111010110
  001110000111100100101110001011101010001100010111110111011011
  111100001000001100010110101100111001001111100100110000001101
  001110010000000111011110000011000010101000111000000110101101
  100100011101011111001101001010011111110010111101000010000111
  110010100110101100001101111101010011000110101100000110001010
  110101101100001110000100010001001010100010110100100001000011
  100100000100001101010101001101000101101000000101111110001010
  101101011010101000111110110000110100000010011111111100110010
  101111000100000100011000010001011111001010010001010110001010
  001010001110101010000100010011101001010101101101010111100101
  001111110000101100010111111100000100101010000001011101100001
  101011110010000010010110000100001010011111100011011000110010
  011110010100011101100101111101000001011100001011010001110011
  000101000101000010010010110111000010101111001101100110011100
  100011100110011111000110011001111100001110110111001001000111
  111011000110001000110111011001011110010010010110101000011111
  011110011110110110011011001011010000100100101010110000010011
  010011110011100101010101111010001001001111101111101110011101
  如果从一个标为 1 的位置可以通过上下左右走到另一个标为 1 的位置,则称两个位置连通。与某一个标为 1 的位置连通的所有位置(包括自己)组成一个连通分块。
  请问矩阵中最大的连通分块有多大?

方法一:深度优先搜索(dfs)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class lianxi {
   static int[] dx = {0, 0, -1, 1};
   static int[] dy = {-1, 1, 0, 0};

   public static void main(String[] args) throws IOException {
      BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
      String[] s;
      int[][] matrix = new int[30][60];

      // 输入矩阵
      for (int i = 0; i < 30; i++) {
         String inputLine = in.readLine();
         for (int j = 0; j < 60; j++) {
            matrix[i][j] = inputLine.charAt(j) - '0';
         }
      }

      int maxConnectedBlock = 0;

      // 遍历矩阵
      for (int i = 0; i < 30; i++) {
         for (int j = 0; j < 60; j++) {
            if (matrix[i][j] == 1) {
               int connectedBlockSize = dfs(i, j, matrix);
               maxConnectedBlock = Math.max(maxConnectedBlock, connectedBlockSize);
            }
         }
      }

      System.out.println("最大连通分块的大小为:" + maxConnectedBlock);
   }

   private static int dfs(int x, int y, int[][] matrix) {
      int size = 1;
      matrix[x][y] = 0; // 标记已访问

      // 遍历上下左右四个方向
      for (int i = 0; i < 4; i++) {
         int newX = x + dx[i];
         int newY = y + dy[i];

         if (newX >= 0 && newX < 30 && newY >= 0 && newY < 60 && matrix[newX][newY] == 1) {
            size += dfs(newX, newY, matrix);
         }
      }

      return size;
   }
}

方法二:广度优先搜索(bfs)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
public class lianxi {
   static int[] dx = {0, 0, -1, 1};
   static int[] dy = {-1, 1, 0, 0};

   public static void main(String[] args) throws IOException {
      BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
      String[] s;
      int[][] G = new int[30][60];
      for (int i = 0; i < 30; i++) {
         String inputLine = in.readLine();
         for (int j = 0; j < 60; j++) {
            G[i][j] = inputLine.charAt(j) - '0'; // 转换字符为整数
         }
      }
      int max = 0;
      //遍历矩阵
      for (int i = 0; i < 30; i++) {
         for (int j = 0; j < 60; j++) {
            if (G[i][j] == 1) {
               boolean[][] st = new boolean[30][60];
               max = Math.max(max, bfs(i, j, st, G));
            }
         }
      }
      System.out.println(max);
   }
   private static int bfs(int x, int y, boolean[][] st, int[][] G) {
      int ans = 1;
      st[x][y] = true;
      Queue<int[]> queue = new LinkedList<>();//bfs结合队列
      queue.offer(new int[]{x, y});
      while (!queue.isEmpty()) {
         int size = queue.size();
         while (size-- > 0) {
            int[] curr = queue.poll();
            int a = curr[0];
            int b = curr[1];
            for (int i = 0; i < 4; i++) {
               int newX = a + dx[i];
               int newY = b + dy[i];
               if (newX >= 0 && newX < 30 && newY >= 0 && newY < 60 && G[newX][newY] == 1 && st[newX][newY] == false) {
                  st[newX][newY] = true;
                  queue.offer(new int[]{newX, newY});
                  ans++;
               }
            }
         }
      }
      return ans;
   }
}

思路总结:像这种bfs,dfs的题目其实大多数的模板都是差不多,把这道题吃透,你就很牛逼啦!

第六题 哪一天

问题描述
  给定一天是一周中的哪天,请问 n 天后是一周中的哪天?
输入格式
  输入第一行包含一个整数 w,表示给定的天是一周中的哪天,w 为 1 到 6 分别表示周一到周六,w 为 7 表示周日。
  第二行包含一个整数 n。
输出格式
  输出一行包含一个整数,表示 n 天后是一周中的哪天,1 到 6 分别表示周一到周六,7 表示周日。
样例输入
6
10
样例输出
2
评测用例规模与约定
  对于所有评测用例,1 <= n <= 1000000。

思路分析:签到题,简单分析下发现一个注意点就是记得取模,好啦直接贴下代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;

public class lianxi {
   public static void main(String[] args) {
      Scanner scanner = new Scanner(System.in);
      int w = scanner.nextInt();
      int n = scanner.nextInt();

      int result = (w + n - 1) % 7;

      // 输出结果,1-6表示周一到周六,7表示周日
      System.out.println(result + 1);
   }
}

第七题 信号覆盖

问题描述

        小蓝负责一块区域的信号塔安装,整块区域是一个长方形区域,建立坐标轴后,西南角坐标为 (0, 0), 东南角坐标为 (W, 0), 西北角坐标为 (0, H), 东北角坐标为 (W, H)。其中 W, H 都是整数。
        他在 n 个位置设置了信号塔,每个信号塔可以覆盖以自己为圆心,半径为 R 的圆形(包括边缘)。
        为了对信号覆盖的情况进行检查,小蓝打算在区域内的所有横纵坐标为整数的点进行测试,检查信号状态。其中横坐标范围为 0 到 W,纵坐标范围为 0 到 H,总共测试 (W+1) * (H+1) 个点。
        给定信号塔的位置,请问这 (W+1)*(H+1) 个点中有多少个点被信号覆盖。

输入格式

        输入第一行包含四个整数 W, H, n, R,相邻整数之间使用一个空格分隔。
        接下来 n 行,每行包含两个整数 x, y,表示一个信号塔的坐标。信号塔可能重合,表示两个信号发射器装在了同一个位置。

输出格式

        输出一行包含一个整数,表示答案。

样例输入

10 10 2 5
0 0
7 0

样例输出

57

评测用例规模与约定

        对于所有评测用例,1 <= W, H <= 100,1 <= n <= 100, 1 <= R <= 100, 0 <= x <= W, 0 <= y <= H。


import java.util.Scanner;

public class lianxi {
   public static void main(String[] args) {
      Scanner scanner = new Scanner(System.in);
      int W = scanner.nextInt();
      int H = scanner.nextInt();
      int n = scanner.nextInt();
      int R = scanner.nextInt();
      int[][] st = new int[n][2];
      for(int i=0;i<n;i++) {
         st[i][0] = scanner.nextInt();
         st[i][1] = scanner.nextInt();
      }

      int sum=0;
      for(int i=0;i<=W;i++) {
         for(int j=0;j<=H;j++) {
            for(int k=0;k<st.length;k++) {                //千万小心精度
               double dis = Math.pow((double)((i-st[k][0])*(i-st[k][0]) + (j-st[k][1])*(j-st[k][1])), (double)1/(double)2);//难点!
               if(dis<=R) {        //但凡该点满足点到圆心的距离
                  sum++;
                  break;
               }
            }
         }
      }
      System.out.println(sum);
   }
}

第八题 清理水域

问题描述

        小蓝有一个 n * m 大小的矩形水域,小蓝将这个水域划分为 n 行 m 列,行数从 1 到 n 标号,列数从 1 到 m 标号。每行和每列的宽度都是单位 1 。
        现在,这个水域长满了水草,小蓝要清理水草。
        每次,小蓝可以清理一块矩形的区域,从第 r1 行(含)到第 r2 行(含)的第 c1 列(含)到 c2 列(含)。
        经过一段时间清理后,请问还有多少地方没有被清理过。

输入格式

        输入第一行包含两个整数 n, m,用一个空格分隔。
        第二行包含一个整数 t ,表示清理的次数。
        接下来 t 行,每行四个整数 r1, c1, r2, c2,相邻整数之间用一个空格分隔,表示一次清理。请注意输入的顺序。

输出格式

        输出一行包含一个整数,表示没有被清理过的面积。

样例输入1

2 3
2
1 1 1 3
1 2 2 2

样例输出1

2

样例输入2

30 20
2
5 5 10 15
6 7 15 9

样例输出2

519

评测用例规模与约定

        对于所有评测用例,1 <= r1 <= r2 <= n <= 100, 1 <= c1 <= c2 <= m <= 100, 0 <= t <= 100。

第九题 最长滑行距离

问题描述
  小蓝准备在一个空旷的场地里面滑行,这个场地的高度不一,小蓝用一个 n 行 m 列的矩阵来表示场地,矩阵中的数值表示场地的高度。
  如果小蓝在某个位置,而他上、下、左、右中有一个位置的高度(严格)低于当前的高度,小蓝就可以滑过去,滑动距离为 1 。
  如果小蓝在某个位置,而他上、下、左、右中所有位置的高度都大于等于当前的高度,小蓝的滑行就结束了。
  小蓝不能滑出矩阵所表示的场地。
  小蓝可以任意选择一个位置开始滑行,请问小蓝最多能滑行多远距离。
输入格式
  输入第一行包含两个整数 n, m,用一个空格分隔。
  接下来 n 行,每行包含 m 个整数,相邻整数之间用一个空格分隔,依次表示每个位置的高度。
输出格式
  输出一行包含一个整数,表示答案。
样例输入
4 5
1 4 6 3 1
11 8 7 3 1
9 4 5 2 1
1 3 2 2 1
样例输出
7
样例说明
  滑行的位置一次为 (2, 1), (2, 2), (2, 3), (3, 3), (3, 2), (4, 2), (4, 3)。
评测用例规模与约定
  对于 30% 评测用例,1 <= n <= 20,1 <= m <= 20,0 <= 高度 <= 100。
  对于所有评测用例,1 <= n <= 100,1 <= m <= 100,0 <= 高度 <= 10000。

方法:bfs暴力搜索

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class lianxi {
   static int[] dx = {0, 0, 1, -1};
   static int[] dy = {1, -1, 0, 0};
   static int max;

   public static void main(String[] args) throws IOException {
      BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
      String[] strings = in.readLine().split(" ");
      int n = Integer.parseInt(strings[0]);
      int m = Integer.parseInt(strings[1]);
      int[][] G = new int[n + 1][m + 1];
      for (int i = 1; i <= n; i++) {
         strings = in.readLine().split(" ");
         for (int j = 1; j <= m; j++) {
            G[i][j] = Integer.parseInt(strings[j - 1]);
         }
      }
      int ans = 0;
      for (int i = 1; i <= n; i++) {
         for (int j = 1; j <= m; j++) {
            max = 0;
            dfs(n, m, i, j, 1, G);
            ans = Math.max(ans, max);
         }
      }
      System.out.println(ans);
   }

   private static void dfs(int n, int m, int x, int y, int step, int[][] G) {
      for (int i = 0; i < 4; i++) {
         int newx = x + dx[i];
         int newy = y + dy[i];
         if (newx >= 1 && newx <= n && newy >= 1 && newy <= m && G[newx][newy] < G[x][y]) {
            step++;
            max = Math.max(max, step);
            dfs(n, m, newx, newy, step, G);
            step--;
         }
      }
   }
}

十 .序列最小值

问题描述
小蓝有一个序列a[1], a[2], ... a[n]。
给定一个正整数k,请问对于每一个1到n之间的序号i, a[i-k], a[i-k+1], .…., a[i+k] 这2k+1个数中的最小值是多少?当某个下标超过1到n的范围时,数不存在,求最小值时只取存在的那些值。输入格式
输入的第一行包含一整数n.
第二行包含n个整数,分别表示a[1], a[2], ... a[n]。第三行包含一个整数k。
输出格式
输出一行,包含n个整数,分别表示对于每个序号求得的最小值。

样例输入

5

5 2 7 4 3

1

样例输出
2 2 2 3 3

思路分析:滑动窗口

import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
  //思路:从整体看,定义一个滑动窗口[i-k,i+k],每次i++,窗口右移一格,寻找最小值
    static int[] a;
    static int min = Integer.MAX_VALUE;//存储当前滑动窗口内的最小值

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        a = new int[n];
        for (int i = 0; i < n; i++) {
            a[i] = scan.nextInt();
        }
        int k = scan.nextInt();
        scan.close();

        //i = 0 ,寻找[0,k]区间的最小值
        findMin(0, k);
        for (int i = 0; i < n; i++) {
            int l = Math.max(i - k, 0);//滑动窗口左边界
            int r = Math.min(i + k, n - 1);//滑动窗口右边界

            //窗口新增加的元素a[r]比上一次窗口的最小值要小或相等,则目前窗口的最小值为a[r]
            if (a[r] <= min) {
                min = a[r];
            } else {
                //当前滑动窗口左边界的左边已经存在数,且左边界值为上一次滑动窗口的最小值,则需要再寻找一次最小值
                if (i - k > 0 && a[l-1] == min) {
                    findMin(l, r);
                }
            }
            System.out.print(min + " ");
        }

    }


    static void findMin(int start, int end) {
        min = Integer.MAX_VALUE;
        for (int i = start; i <= end; i++) {
            min = Math.min(min, a[i]);
        }
    }
}

十一 .数位和最小

问题描述
一个数的数位和是指这个数各个数位上的数字之和。例如2023的数位和是2+0+2+3=7.
对于以下这些数(8行,每行8个,共64个),请问数位和最小的数是多少?(如果有多个,请回答出现最早的那个)

454771 329157 801601 580793 755604 931703 529875 361797

604358 529564 574776 821517 195563 688516 223321 607845

284772 603562 543328 707484 533688 380468 233733 257995

896582 670074 912386 702393 722092 834842 126346 606526

376981 910643 413754 945725 817853 651778 350775 676550

316935 487808 939526 900568 423326 298936 927671 539773

136326 717022 886675 466684 436470 558644 267231 902422

743580 857864 529622 320921 595409 486860 951114 558787

思路分析:使用字符串分割成字符数组,对每个数字逐位相加,算法没什么精妙的,但可以用库函数 ,nice啊!

import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    public static void main(String[] args) {
       String num="454771 329157 801601 580793 755604 931703 529875 361797 " +
               "604358 529564 574776 821517 195563 688516 223321 607845 " +
               "284772 603562 543328 707484 533688 380468 233733 257995 " +
               "896582 670074 912386 702393 722092 834842 126346 606526 " +
               "376981 910643 413754 945725 817853 651778 350775 676550 " +
               "316935 487808 939526 900568 423326 298936 927671 539773 " +
               "136326 717022 886675 466684 436470 558644 267231 902422 " +
               "743580 857864 529622 320921 595409 486860 951114 558787";
       String[] str=num.split(" ");

       int k=0;

       int tmp=0,min=Integer.MAX_VALUE;
       for (int i=0;i<str.length;i++){
           tmp=0;
           for (int j=0;j<6;j++){
               tmp=tmp+(int)str[i].charAt(j);

           }
           if (tmp<min){
           min=tmp;
           k=i;}
       }

        System.out.println(Integer.valueOf(str[k]));
    }
}

十二 .对折绳子

问题描述
  小蓝有一根长度为 L 的绳子,每对折一次,长度变为原来的一半,请问对折多少次后长度不超过 1 。
  例如,当 L=6 时,对折一次长度为 3,对折两次长度为 1.5 ,对折 3 次长度为 0.75,所以 3 次后长度不超过 1 。
输入格式
  输入一行包含一个整数 L 。
输出格式
  输出一行包含一个整数,表示答案。
样例输入
6
样例输出
3
样例输入
255
样例输出
8
样例输入
256
样例输出
8
样例输入
257
样例输出
9
评测用例规模与约定
  对于 50% 评测用例,1 < L <= 10**9 (10的9次方)。
  对于所有评测用例,1 < L <= 10**18 (10的18次方)。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Double L = scanner.nextDouble();
        long ans = 0;
        while (true) {
            L /= 2;
            ans++;
            if (L <= 1 )break;
        }
        System.out.println(ans);
    }
}

十三 .删除字符

问题描述
  给定一个由大写字母组成的长度为 n 的字符串,请在字符串中删除 m 个字符,使得剩下的字符串的字典序最小。
输入格式
  输入的第一行包含两个整数 n, m ,用一个空格分隔。
  第二行包含一个长度为 n 的字符串。
输出格式
  输出一行包含一个长为 n-m 的字符串,表示答案。
样例输入
7 3
LANQIAO
样例输出
AIAO
评测用例规模与约定
  对于 30% 的评测用例,1 <= m < n <= 30。
  对于 60% 的评测用例,1 <= m < n <= 1000。

思路分析:用模拟枚举即可

方法一:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        String str = scanner.next();

        StringBuilder result = new StringBuilder();
        int deleteCount = 0;

        for (int i = 0; i < n; i++) {
            char c = str.charAt(i);

            while (deleteCount < m && result.length() > 0 && result.charAt(result.length() - 1) > c) {
                result.deleteCharAt(result.length() - 1);
                deleteCount++;
            }

            result.append(c);
        }

        if (deleteCount < m) {
            result.delete(result.length() - (m - deleteCount), result.length());
        }

        System.out.println(result.toString());
    }
}

方法二:双向队列实现栈功能

import java.util.*;

public class lianxi {
   public static void main(String[] args) {
      Scanner scanner = new Scanner(System.in);

      // 读取输入
      int n = scanner.nextInt();
      int m = scanner.nextInt();
      scanner.nextLine(); // 读取换行符
      String input = scanner.nextLine();

      // 使用双向队列实现栈的功能
      Deque<Character> stack = new LinkedList<>();

      // 删除 m 个字符,使得剩下的字符串的字典序最小
      for (char ch : input.toCharArray()) {
         while (m > 0 && !stack.isEmpty() && stack.peekLast() > ch) {
            stack.pollLast();
            m--;
         }
         stack.offerLast(ch);
      }

      // 处理可能剩余的字符
      while (m > 0 && !stack.isEmpty()) {
         stack.pollLast();
         m--;
      }
      // 构建结果字符串
      StringBuilder result = new StringBuilder();
      for (char ch : stack) {
         result.append(ch);
      }
      // 输出结果
      System.out.println(result.toString());
   }
}

以上便是我对这些题目的看法,欢迎大家在评论区积极点赞和提问!感谢!

  • 39
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值