Skip to content

2025 题库(阶段二)

1、 教授分组

有 n 个人,进行分组,分组模式有三种:

  1. 三人一组,要求最高分和最低分相差不超过 10 分;
  2. 二人一组,要求两个人相差不超过 20 分;
  3. 一人一组,分数没有要求;

求最少可以分几组。

解答:

    public static int minGroups(int[] scores) {
        Arrays.sort(scores);
        int groups = 0;
        int n = scores.length;
        int l = 0, r;
        while (l < scores.length) {
            r = l + 2; // 先尝试三人一组
            if (r < n && scores[r] - scores[l] <= 10) {
                l = r + 1; // 符合要求,跳过这三个分数
            } else {
                r = l + 1; // 再尝试二人一组
                if (r < n && scores[r] - scores[l] <= 20) {
                    l = r + 1; // 符合要求,跳过这二个分数
                } else {
                    l = r; // 单人成组
                }
            }
            groups++; // 增加组数
        }
        return groups;
    }

2、 小红的红黑数

小红有一个整数数组,给出一个包含'R'和'B'的字符串,字符串第 i 位上的'R'或'B'标识数组中第 i 个数字为红数或黑数,将一个红数和一个黑数相乘为一个红黑数,求全部红黑数之和,结果对 1000000007 取模。

解答:

    private static final int MOD = 1000000007;

    public static int calcRedBlackSum(int[] nums, String colors) {
        long redSum = 0;
        long blackSum = 0;

        for (int i = 0; i < nums.length; i++) {
            if (colors.charAt(i) == 'R') {
                redSum = (redSum + nums[i]) % MOD;
            } else {
                blackSum = (blackSum + nums[i]) % MOD;
            }
        }

        long result = (redSum * blackSum) % MOD;
        return (int) ((result + MOD) % MOD);  // 确保结果为非负数
    }

3、 相似三角形

给定一个三角形(a,b,c 表示三条边长),然后输入三个数字 x,y,z,判断 x,y,z 是否是三角形,如果不是,输出一行“不是”的字符串,如果是三角形,判断和给定的三角形 a,b,c 是否相似,如果相似,输出“相似”的字符串,否则输出“不相似”的字符串。

解答:

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

        double[] triangle1 = new double[3];
        double[] triangle2 = new double[3];
        for (int i = 0; i < 3; i++) {
            triangle1[i] = scanner.nextDouble();
        }
        for (int i = 0; i < 3; i++) {
            triangle2[i] = scanner.nextDouble();
        }
        Arrays.sort(triangle1);
        Arrays.sort(triangle2);

        if (!isTriangle(triangle1)) {
            System.out.println("第一个三角形不合法,不是三角形");
        } else if (!isSimilar(triangle1, triangle2)) {
            System.out.println("两个三角形不相似");
        } else {
            System.out.println("两个三角形是相似三角形");
        }
    }

    // 判断三边能否组成三角形
    public static boolean isTriangle(double[] sides) {
        return sides[0] + sides[1] > sides[2] &&
                sides[0] + sides[2] > sides[1] &&
                sides[1] + sides[2] > sides[0];
    }

    // 判断两个三角形是否相似(对应边成比例)
    public static boolean isSimilar(double[] triangle1, double[] triangle2) {
        double ratio1 = triangle1[0] / triangle2[0];
        double ratio2 = triangle1[1] / triangle2[1];
        double ratio3 = triangle1[2] / triangle2[2];
        // 使用一个精度范围判断比例是否相等(避免浮点误差)
        return Math.abs(ratio1 - ratio2) < 1e-9 && Math.abs(ratio2 - ratio3) < 1e-9;
    }

4、 最多可以分解为多少个质数

给定一个正整数 n,求 n 最多可以分解为多少个质数之和。如:5=2+3,输出 2。

思路

  • 最小的偶数质数为 2;
  • 最小的奇数质数为 3;
  • 所有的正整数都可以分解为:2+2+...+2+(2+1) 的形式。

解答:

    public static int countPrimeFactors(int n) {
        retuen n / 2;
    }

5、 给学生发短信

给定 n 个学生,m 门课程,老师要给超过超过课程平均分的同学发祝贺短信,求最少需要多少条短信。

解答:

    public static int minMessageCount(int[][] scores) {
        int students = scores.length;
        if (students == 0) return 0;
        int courses = scores[0].length;

        double[] courseAverages = new double[courses];
        for (int c = 0; c < courses; c++) {
            double sum = 0;
            for (int[] score : scores) {
                sum += score[c];
            }
            courseAverages[c] = sum / students;
        }

        int count = 0;
        for (int s = 0; s < students; s++) {
            boolean flag = false;
            for (int c = 0; c < courses; c++) {
                if (scores[s][c] > courseAverages[c]) {
                    flag = true;
                    break;
                }
            }
            if (flag) {
                count++;
            }
        }
        return count;
    }

6、 K 次交换位置

给一个长度为 n 的数组 arr,元素为 ai,共遍历 m 次,k in [1, m],当满足 arr[i] % k > arr[i + 1] % k 时,交换元素位置。输出遍历 K 次后的数组。

解答:

    public static int[] swapNumbers(int[] arr, int m) {
        for (int k = 1; k <= m; k++) {
            for (int i = 0; i < arr.length - 1; i++) {
                if (arr[i] % k > arr[i + 1] % k) {
                    int temp = arr[i];
                    arr[i] = arr[i + 1];
                    arr[i + 1] = temp;
                }
            }
        }
        return arr;
    }

7、 非 1 元素的公约数

给定一个数组,求数组中非 1 元素的最小公约数。

思路

  1. 先计算数组中所有非 1 元素的最大公约数;
  2. 如果 GCD 为 1,则没有非 1 公约数;
  3. 找出 GCD 中最小的非 1 质因数。

解答:

    public static int gcd(int a, int b) {
        if (b == 0) return a;
        return gcd(b, a % b);
    }

    public static int gcdExOne(int[] nums) {
        // 先过滤出非1元素
        int[] filtered = Arrays.stream(nums).filter(x -> x != 1).toArray();
        if (filtered.length == 0) return 1;
        // 计算最大公约数GCD
        int result = filtered[0];
        for (int i = 1; i < filtered.length; i++) {
            result = gcd(result, filtered[i]);
            if (result == 1) {
                break;
            }
        }
        if (result == 1) return -1;
        // 找出最小质因数
        for (int i = 2; i * i <= result; i++) {
            if (result % i == 0) return i;
        }
        return result;
    }

8、 通过异或和找出丢失的数

给定一个 sum 为 1~n 的异或和,但在求和过程中少了一个数(如:n=5,sum=1^2^4^5),求出缺失的数。

思路

用到异或运算的重要性质:

  1. 交换律与结合律 ‌。这使得异或运算的顺序不影响最终结果。‌‌
交换律:a ⊕ b = b ⊕ a。
结合律:a ⊕ (b ⊕ c) = (a ⊕ b) ⊕ c。
  1. 恒等律与归零律 ‌。
恒等律:a ⊕ 0 = a(任何数与0异或结果不变)。
归零律:a ⊕ a = 0(任何数与自身异或结果为0)。‌‌
  1. ‌ 自反性与可逆性 ‌。
自反性:a ⊕ b ⊕ b = a(连续两次异或同一数可还原原值)。
推论:若 a ⊕ b = c,则 a ⊕ c = b 且 b ⊕ c = a。‌‌
  1. ‌ 分配律(与 AND 运算结合)‌。
a & (b ⊕ c) = (a & b) ⊕ (a & c)。‌‌

本题主要使用的是可逆性的推论。

解答:

    public static int findMissingNum(int n, int xorSum) {
        int curSum = 0;
        for (int k = 1; k <= n; k++) {
            curSum ^= k;
        }
        return curSum ^ xorSum;
    }

9、 左侧有几个不同的值

给定一个 01 串,遍历这个字符串,输出当前下标左侧有多少个不同的数值。

示例:

输入:01101
输出:01222

解答:

    public static String countNum(String source) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < source.length(); i++) {
            Set<Character> set = new HashSet<>();
            for (int j = 0; j < i; j++) {
                set.add(source.charAt(j));
            }
            sb.append(set.size());
        }
        return sb.toString();
    }

10、 可调顺序极差和

给定长度为 n 的整数,可调整各位上数字的顺序,如:154937→134579,求各位之间的差值和的最大值。如:(9-1)+(7-3)+(5-4)

解答:

    public static int maxSum(int n) {
        char[] digits = String.valueOf(n).toCharArray();
        Arrays.sort(digits);

        int l = 0;
        int r = digits.length - 1;
        int sum = 0;
        while (l < r) {
            sum = digits[r] - digits[l];
            l++;
            r--;
        }
        return sum;
    }

11、 鸵鸟吃东西

输入一个数组 arr,数组中的元素表示食物的高度;输入一个值 h,表示鸵鸟的高度;鸵鸟只能吃到高度小于等于它身高的食物,鸵鸟每吃一个食物身高+1;求鸵鸟最终的身高。

解答:

    public static int ostrichHeight(int[] arr, int h) {
        Arrays.sort(arr);
        int height = h;
        for (int i : arr) {
            if (i <= height) {
                height++;
            }
        }
        return height;
    }

12、 相邻字母最长串

给一个字符串,如果两个原字母表中相邻字母,在这个串里也相邻,则为好串,求这个串里最长好串长度。

解答:

    public static int maxLen(String s) {
        if (s == null || s.isEmpty()) return 0;
        int maxLen = 1;
        int curLen = 1;
        char[] chars = s.toCharArray();
        for (int i = 1; i < chars.length; i++) {
            if (Math.abs(chars[i] - chars[i - 1]) == 1) {
                curLen++;
                maxLen = Math.max(curLen, maxLen);
            } else {
                curLen = 1;
            }
        }
        return maxLen;
    }

13、 变换字符串最小代价

输入一个字符串,变化规则如下:

  1. 同为大写字母可以变换,如:A→B;
  2. 同为小写字母可以变换,如:a→b;
  3. 字母大小写可以变换,如:A→a;

每次变换的代价为 5,求字符串中包含“AcMer”的最小代价。

解答:

    public static int minCost(String s, String t) {
        int n = s.length();
        if (n < t.length()) return -1;

        int minCost = Integer.MAX_VALUE;
        int curCost;
        char cs, ct;
        for (int i = 0; i <= n - t.length(); i++) {
            curCost = 0;
            for (int j = 0; j < t.length(); j++) {
                cs = s.charAt(i + j);
                ct = t.charAt(j);
                // 如果忽略大小写相同
                if (Character.toLowerCase(cs) == Character.toLowerCase(ct)) {
                    if (cs != ct) {
                        curCost += 5; // 仅大小写不同,需要转换
                    }
                } else {
                    curCost += 5; // 完全不同字符,需要替换
                }
            }
            minCost = Math.min(curCost, minCost);
        }
        return minCost;
    }

14、 僵尸数组

给定一个二维数组,其中元素不为 0,且可以相互连接起来的称为一堆僵尸,一个数单独的也可称为一堆,求一共有多少堆僵尸。

解答:

    public static int clusterZombies(int[][] source) {
        if (source == null || source.length == 0 || source[0].length == 0) {
            return 0;
        }
        int count = 0;
        int rows = source.length;
        int cols = source[0].length;
        for (int row = 0; row < rows; row++) {
            for (int col = 0; col < cols; col++) {
                if (source[row][col] == 1) { // 发现未访问的非零元素
                    count++; // 增加区域计数
                    dfs(source, row, col); // 标记相邻区域
                }
            }
        }
        return count;
    }

    public static void dfs(int[][] grid, int i, int j) {
        if (i < 0 || i >= grid.length || j < 0 || j >= grid[0].length) {
            return; // 边界检测
        }
        if (grid[i][j] == 0) {
            return; // 没有僵尸
        }
        grid[i][j] = 0; // 标记已访问元素
        // 递归检查四周
        dfs(grid, i + 1, j); // 下
        dfs(grid, i - 1, j); // 上
        dfs(grid, i, j + 1); // 右
        dfs(grid, i, j - 1); // 左
    }

15、 小红串

给定一个全部为小写字符的字符串,如果这个字符串中所有的字符左右都是字母表中相邻的字符,则这个字符串可以被称为小红串, 比如 babc 是小红串,red 不是小红串。现在给出一个全部为小写字符的字符串,尽可能少的移除其中的字符,使字符串符合小红串的定义,求最终所能达到的最长的小红串的长度。例:baab ,当移除一个 a 时,符合小红串定义,最长为 3。

解答:

    public static int longestRedString(String s) {
        if (s == null || s.isEmpty()) {
            return 0;
        }
        int[] dp = new int[s.length()];
        Arrays.fill(dp, 1);
        int maxLen = 1;
        for (int i = 1; i < s.length(); i++) {
            for (int j = 0; j < i; j++) {
                if (Math.abs(s.charAt(i) - s.charAt(j)) == 1) {
                    dp[i] = Math.max(dp[i], dp[j] + 1);
                }
            }
            maxLen = Math.max(dp[i], maxLen);
        }
        return maxLen;
    }

16、 绘制“里”字

一个正整数 n,代表里字的大小(1<=n<=30);输出一个 11n 行,每行长度为 11n 列,仅包含“.”和“*”的字符串,这些字符串从视觉上组成“里”字。

示例:

输入:n = 1
> ...........
> ..*******..
> ..*..*..*..
> ..*******..
> ..*..*..*..
> ..*******..
> .....*.....
> ..*******..
> .....*.....
> .*********.
> ...........
输入:n = 2
> ......................
> ......................
> ....**************....
> ....**************....
> ....**....**....**....
> ....**....**....**....
> ....**************....
> ....**************....
> ....**....**....**....
> ....**....**....**....
> ....**************....
> ....**************....
> ..........**..........
> ..........**..........
> ....**************....
> ....**************....
> ..........**..........
> ..........**..........
> ..******************..
> ..******************..
> ......................
> ......................

解答:

    public static void drawLi(int n) {
        int size = 11 * n;
        String dots = ".".repeat(size);
        String starLine = ".".repeat(2 * n) + "*".repeat(7 * n) + ".".repeat(2 * n);
        String dash3Str = ".".repeat(2 * n) + "*".repeat(n) + ".".repeat(2 * n) + "*".repeat(n) + ".".repeat(2 * n) + "*".repeat(n) + ".".repeat(2 * n);
        String dash1Str = ".".repeat(5 * n) + "*".repeat(n) + ".".repeat(5 * n);
        String lastLine = ".".repeat(n) + "*".repeat(9 * n) + ".".repeat(n);
        int j;
        for (int i = 0; i < size; i++) {
            j = i / n % 11;
            if (j == 9) {
                System.out.println(lastLine);
            } else if (j == 1 || j == 3 || j == 5 || j == 7) {
                System.out.println(starLine);
            } else if (j == 2 || j == 4) {
                System.out.println(dash3Str);
            } else if (j == 6 || j == 8) {
                System.out.println(dash1Str);
            } else {
                System.out.println(dots);
            }
        }
    }

    // 如果没有String.repeat(n)方法,可以用下面方法替换
    public static String repeat(char c, int n) {
        char[] chars = new char[n];
        Arrays.fill(chars, c);
        return new String(chars);
    }

17、 方卡

有 m 张方卡,每张方卡中包含 2*n 个方格,每个方格有两种颜色红色和绿色。当红色的方格数量大于等于绿色的方格数量时,为有效卡。绿色方格可以转变为红色方格。求使 m-1 张方卡转变为有效卡时,转变次数最少为多少?

第一行输入 n,m,m 表示有 m 张方卡;然后输入 m 行,每行两个数分别表示红色卡片的数量、绿色卡片的数量;输出:若至少有 m-1 组合格,输出最少代价。

解答:

解答:

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int[] cost = new int[m];
        int r;
        int g;
        for (int i = 0; i < m; i++) {
            r = sc.nextInt();
            g = sc.nextInt();
            if (r < g) {
                cost[i] = (g - r) / 2;
            } else {
                cost[i] = 0;
            }
        }
        Arrays.sort(cost);

        int result = 0;
        for (int i = 0; i < cost.length - 1; i++) {
            result = result + cost[i];
        }
        System.out.print(result);
    }

18、 小红的好方格

给定一个 n*m 的矩阵,矩阵中元素的值以'R','B'和'W'分别表示红,蓝,白三种颜色。定义一个红色元素的上下左右其中一个为蓝色,则为好方格。输出该矩阵中好方格的数目。

示例:

输入:
RWBR
RRWW
BWWB
输出:
2

解答:

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        String[][] arr = new String[n][m];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                arr[i][j] = sc.next();
            }
        }

        int count = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                String s = arr[i][j];
                if (s.equals("R")) {
                    int l = j - 1;
                    int r = j + 1;
                    int t = i - 1;
                    int b = i + 1;
                    if (l >= 0 && "B".equals(arr[i][l])) {
                        count++;
                        continue;
                    }
                    if (r < m && "B".equals(arr[i][r])) {
                        count++;
                        continue;
                    }
                    if (t >= 0 && "B".equals(arr[t][j])) {
                        count++;
                        continue;
                    }
                    if (b < n && "B".equals(arr[b][j])) {
                        count++;
                        continue;
                    }
                }
            }
        }
        System.out.print(count);
    }

19、 数组归零

给定一组数,选择任意个元素减去 2 的 k 次方,问最少多少次,使得数组全为 0。

解答:

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int bits = 0;
        while (sc.hasNext()) {
            bits |= sc.nextInt();
        }
        int result = Integer.bitCount(bits);
        System.out.print(result);
    }

20、 最大正方形

给定一个长度为 n 的数组,每个元素表示木板长度,木板宽度固定为 1,现在把它们竖着拼在起之后切割出一块正方形,求能得到的正方形的最大边长。

解答:

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        Integer[] array = new Integer[n];
        for (int i = 0; i < n; i++) {
            array[i] = in.nextInt();
        }
        Arrays.sort(array, Collections.reverseOrder());
        int maxSide = 0;
        for (int i = 0; i < array.length; i++) {
            if (array[i] >= i + 1) maxSide = i + 1;
        }
        System.out.print(maxSide);
    }

21、 AB 字符串

判断一个字符串是否是插入 ab 形成的。

示例:

aabb,是在ab之间插入ab形成
abab,是在ab前/后插入ab形成
aabbb,不满足条件
baba,不满足条件

解答:

    public static boolean isABStr(String s) {
        while (s.contains("ab")) {
            s = s.replaceAll("ab", "");
        }
        return s.isEmpty();
    }

22、 六边形求面积

能力六边形求面积,给出正六边形边长 l,每项能力边长与分数成正比,求阴影部分的面积。

解答:

    public static double hexagonArea(int length, int[] grades, int[] totals) {
        double sin60 = Math.sin(Math.PI / 3);
        double areaSum = 0f;
        for (int i = 0; i < 6; i++) {
            areaSum += (grades[i] * length) * (grades[(i + 1) % 6] * length * sin60) / 2;
        }
        return areaSum / 10000;
    }

23、 好串的最大个数

给定长度为 n 的字符串 s,定义相同字母连续且不重复的长度为 k,则称为好串;求这个字符串中好串的最大个数。

示例:

输入:7 2 aabbaac
输出:2,因为有2个aa
    public static int maxCount(int n, int k, String s) {
        Map<Character, Integer> map = new HashMap<>();
        char c;
        for (int i = 0; i <= n - k; ) {
            boolean isGood = true;
            c = s.charAt(i);
            for (int j = 1; j < k; j++) {
                if (c != s.charAt(i + j)) {
                    isGood = false;
                    break;
                }
            }
            if (isGood) {
                map.put(c, map.getOrDefault(c, 0) + 1);
                i += k;
            } else {
                i++;
            }
        }
        return Collections.max(map.values());
    }

24、 小红的数组修改

给定一个长度为 n 的数组,数组中每个元素每次可以+1 或-1,最终要使得数组中的元素不小于 k,并且平均值等于 m,问最少要操作几次?

示例:

输入:n=5 m=3 k=3
5 3 3
1 1 2 3 3
输出:5

解答:

    public static int countOpt(int[] arr, int k, int m) {
        int arrSum = 0;
        int minOpt = 0; // 使所有元素不小于K的操作数
        for (int a : arr) {
            if (a < k) {
                minOpt += k - a;
                arrSum += k;
            } else {
                arrSum += a;
            }
        }
        int avgOpt = Math.abs(m * arr.length - arrSum); // 使数组平均值等于m的操作数
        return avgOpt + minOpt;
    }

25、 小红的数组删除

给定一个数组 vec,如果 abs(vec[i]-vec[j]<=1),则可以在数组中把大的元素删除,相同则随机删除一个,问是否能够删除完后数组只剩下一个元素?

解答:

    public static boolean remainOne(int[] arr) {
        Arrays.sort(arr);
        boolean result = true;
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] - arr[i - 1] > 1) {
                result = false;
                break;
            }
        }
        return result;
    }

26、 三个任务最小花费

有 3 个需要完成的任务,完成这 3 个任务是需要付出代价的。首先,你可以不花费任何代价的完成第一个任务,然后在完成了第 i 个任务之后,需要花费|A(i)-A(j)|的代价完成第 j 个任务,输出完成 3 任务的最小代价。

解答:

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int[] array = new int[3];
        for (int i = 0; i < 3; i++) {
            array[i] = in.nextInt();
        }
        Arrays.sort(array);
        int cost = array[2] - array[1] + array[1] - array[0];
        System.out.print(cost);
    }

27、 打光子弹

弹夹总容量为 m,一次性装满需要 a 分钟,一次装一颗子弹需要 b 分钟,开枪一次需要一分钟,问需要多久能将 n 颗子弹打完,注意:一开始弹夹内没有子弹。

解答:

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int a = sc.nextInt();
        int b = sc.nextInt();
        int rounds = n / m;
        int remain = n % m;
        int roundsTime = Math.min(a, b * m) + m;
        int remainTime = Math.min(a, b * remain) + remain;
        int minutes = rounds * roundsTime + remainTime;
        System.out.print(minutes);
    }

28、 池化 cnn

给一个 nn(n 是 2 的指数,类似于 44,88,1616)的数组(数字任意,没有任何规律),将其拆分为 2*2 的矩阵,每次取矩阵里的倒数第二大的数字,得到一个新的矩阵,重复上述操作,直到矩阵大小为 1,求最后能剩下几。

示例:

c0 c1 c2 c3
r0 1 2 3 4
r1 5 6 7 8
r2 9 10 11 12
r3 8 14 15 16

第一次操作后得到的新矩阵为:

c0 c1
r0 5 7
r1 10 15

需要继续进行池化操作,最后得到 10。

解答:

    public static int poolingOne(int[][] matrix) {
        while (matrix.length > 1) {
            matrix = poolingOpt(matrix);
        }
        return matrix[0][0];
    }

    public static int[][] poolingOpt(int[][] matrix) {
        int newSize = matrix.length / 2;
        int[][] output = new int[newSize][newSize];
        // 遍历每个2×2块
        for (int i = 0; i < newSize; i++) {
            for (int j = 0; j < newSize; j++) {
                // 提取当前2×2块
                int[] block = {
                        matrix[2 * i][2 * j],        // 左上
                        matrix[2 * i][2 * j + 1],    // 右上
                        matrix[2 * i + 1][2 * j],    // 左下
                        matrix[2 * i + 1][2 * j + 1] // 右下
                };
                Arrays.sort(block); // 排序块内元素(升序)
                output[i][j] = block[2];
            }
        }
        return output;
    }

29、 区间操作

给定一个数组 vec,长度为 len,初始值全为 0,求经过如下的 q 次区间操作,最后的 vec 值。

区间操作:对[l,r]中的数组的元素,如果元素下标是 v 的倍数,则对应的元素+1。

输入:

n q
li ri vi
...
lq rq vq

解答:

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int q = in.nextInt();
        int[] vec = new int[n];
        int li, ri, vi;
        for (int i = 0; i < q; i++) {
            li = in.nextInt();
            ri = in.nextInt();
            vi = in.nextInt();
            for (int j = li; j <= ri; j++) {
                if (j % vi == 0) vec[j]++;
            }
        }
        Arrays.stream(vec).forEach(a -> System.out.print(a + " "));
    }

30、 牛牛的 01 串

牛牛有长度为 n 的 01 串 s,s="s1s2..sn"(下标从 1 开始)。定义位置 i(1<=i<=n)定义:(1)ai 为在 i 左侧(下标 < i 的位置),字符与 si 不同的元素个数;请你输出整个序列{a1, a2,…..an}。

输入:
每个测试文件均包含多组测试数据,第一行输入一个整数T(1~100)代表数据组数,每组测
试数据描述如下:
在第一行输入一个整数n(1~10^3),表示字符串长度;在第二行输入一个长度为n,仅由字
符'0'和'1'组成的字符串s,表示初始字符串;
输出:
对于每组测试数据,新起一行,按顺序输出n个整数a1,a2....an,相邻整数之间用一个空
格分割;

解答:

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        for (int i = 0; i < t; i++) {
            int n = sc.nextInt();
            String s = sc.next();
            StringBuilder sb = new StringBuilder();
            for (int j = 0; j < n; j++) {
                char target = s.charAt(j);
                String ss = s.substring(0, j);
                long count = ss.chars().filter(c -> c != target).count();
                sb.append(count).append(" ");
            }
            System.out.println(sb);
        }
    }

31、 敏感词检测

输入长度 n 的 txt 字符串,输入敏感词 m 个 ,如"happy"“wondeful”,统计心情指标,即敏感词总数。

输入 长度 n 和 m(敏感词个数)
输入字符串: "wondefulllllgdfgdfhappygsasf"
输入 "happy"
输入 "wondeful"
输出 2

解答:

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        String text = sc.next();
        int result = 0;
        for (int i = 0; i < m; i++) {
            String keyword = sc.next();
            result = result + checkStr(text, keyword);
        }
        System.out.println(result);
    }

    public static int checkStr(String text, String keyword) {
        int index = 0;
        int count = 0;
        while ((index = text.indexOf(keyword, index)) != -1) {
            index = index + keyword.length();
            count++;
        }
        return count;
    }

32、 分苹果

有 m 个苹果,n 个学生,要求每个学生都能分到至少一个苹果,要求相邻编号的小孩分到的苹果数量差距不超过 1,小明在 k 号位置,求小明分到苹果最多是多少?

解答:

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int m = sc.nextInt(); // 苹果总数
        int n = sc.nextInt(); // 学生人数
        int k = sc.nextInt(); // 小明位置(1-based)
        System.out.println(maxApples(m, n, k));
    }

    private static int maxApples(int m, int n, int k) {
        int left = k - 1;  // 左边人数
        int right = n - k; // 右边人数
        int low = 1, high = m - n + 1;
        int result = 1;

        while (low <= high) {
            int mid = (low + high) / 2;
            long total = calcTotal(mid, left, right);
            if (total <= m) {
                result = mid;
                low = mid + 1;
            } else {
                high = mid - 1;
            }
        }
        return result;
    }

    private static long calcTotal(int x, int left, int right) {
        return x + calcSide(x - 1, left) + calcSide(x - 1, right);
    }

    private static long calcSide(int peak, int len) {
        if (peak >= len) {
            long first = peak - len + 1;
            return (first + peak) * len / 2;
        } else {
            long full = (1L + peak) * peak / 2;
            return full + (len - peak);
        }
    }