2025 题库(阶段二)
1、 教授分组
有 n 个人,进行分组,分组模式有三种:
- 三人一组,要求最高分和最低分相差不超过 10 分;
- 二人一组,要求两个人相差不超过 20 分;
- 一人一组,分数没有要求;
求最少可以分几组。
解答:
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 元素的最大公约数;
- 如果 GCD 为 1,则没有非 1 公约数;
- 找出 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),求出缺失的数。
思路
用到异或运算的重要性质:
- 交换律与结合律 。这使得异或运算的顺序不影响最终结果。
交换律:a ⊕ b = b ⊕ a。
结合律:a ⊕ (b ⊕ c) = (a ⊕ b) ⊕ c。
- 恒等律与归零律 。
恒等律:a ⊕ 0 = a(任何数与0异或结果不变)。
归零律:a ⊕ a = 0(任何数与自身异或结果为0)。
- 自反性与可逆性 。
自反性:a ⊕ b ⊕ b = a(连续两次异或同一数可还原原值)。
推论:若 a ⊕ b = c,则 a ⊕ c = b 且 b ⊕ c = a。
- 分配律(与 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、 变换字符串最小代价
输入一个字符串,变化规则如下:
- 同为大写字母可以变换,如:A→B;
- 同为小写字母可以变换,如:a→b;
- 字母大小写可以变换,如: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);
}
}