本篇博客旨在记录自已的算法刷题练习成长,里面注有详细的代码注释以及和个人的思路想法,希望可以给同道之人些许帮助。本人也是算法小白,水平有限,如果文章中有什么错误或遗漏之处,望各位可以在评论区指正出来,各位共勉💪。
1、38红包
2025 年38 妇女节这天,公司里热闹非凡,老板突发奇想,决定给员工们发发节日红包玩。他召集了全体员工,大手一挥:”咱们公司有2025 个员工,每人都有个编号,从1排到 2025。今天是 38 节,凡是编号跟 3、8、38 沾点边的同事,都能领一个红包!一人一个,不重复领啊!”
小李一听,赶紧问:“老板,啥叫’沾点边"啊?
老板笑眯眯地说:“就是编号要是3 的倍数,或者8的倍数,或者38的倍数,明白了吧?
小张凑过来捣乱:“那我编号是 38 的平方,是不是能多领一个?
老板翻了个白眼:“想得美!说了不重复,你就是 38 的立方,也就一个红包!"
结果,小王跳出来喊:“老板,我编号是0咋办?”
老板愣了下,随即哈哈大笑:“咱们从1开始编号,哪儿来的 0啊?你小子是来蹭红包的吧!
现在,请你算算,老板总共得发多少个红包?
解题代码:
public class Main {
public static void main(String[] args) {
int count = 0;
for (int i = 1; i <= 2025; i++) {
if (i % 3 ==0 || i % 8==0 || i % 38 ==0){
count++;
}
}
System.out.println(count);
}
}
2、祝福语
三月八日国际劳动妇女节即将来临,小蓝和小桥都想为自己的母亲送上一份特别的节日祝福。
小蓝已经用心准备了一条充满深情的祝福语,用仅包含小写字母的字符串 S 表示。小桥同样希望表达对母亲的爱意,但为了避免与小蓝的祝福语重复,她决定设计一条独特的祝福语 T,要求工 不能是 S 的部分(即 T 不是 S 的子串)。同时,T也必须仅由小写字母构成。
为了让祝福语更具新意,小桥还希望在所有满足上述条件的祝福语中,工 的字典序是最小的。
输入格式:
输入一行,包含一个仅由小写字母构成的字符串 S(1≤∣S∣≤105),表示小蓝的祝福语。
输出格式:
输出一个仅由小写字母构成的字符串 T,表示小桥的祝福语。
解题代码:
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
// 统计字符串的长度
int count = 0, max = 0;
// 遍历字符串s中的字符,找出最长的a字符串
for(int i=0;i<s.length();i++) {
if(s.charAt(i)=='a') {
count++;
max = Math.max(max, count);
}else {
count=0;
}
}
for(int i=0;i<=max;i++) System.out.print('a');
}
}
3、社区服务
为了庆祝妇女节,社区组织了一场“温暖传递”活动。社区中有 n 个服务点排成一列,每个服务点可能有志愿者(用 1
表示)或暂时无人(用 0
表示)。
每个服务点都有居民需要帮助,现在你需要从左往右,为每个无志愿者服务点计算距离最近的有志愿者服务点的距离,若不存在则输出 −1。
输入格式:
第一行输入一个整数 n(1≤n≤5000),表示服务点数量。
第二行输入一个长度为 n 的二进制字符串 S,1
表示当前服务点有志愿者,0
表示当前服务点无志愿者。
数据保证 S 至少包含 1 个 0
。
输出格式:
输出一行若干个整数,表示每个无志愿者服务点到有志愿者服务点的最近距离,若不存在则输出 −1。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String S = scanner.next();
scanner.close();
// 记录S中所有可能的子串(限制最大长度为 5)
HashSet<String> subStrings = new HashSet<>();
int len = S.length();
for (int i = 0; i < len; i++) {
StringBuilder sb = new StringBuilder();
for (int j = i; j < Math.min(i + 5, len); j++) {
sb.append(S.charAt(j));
subStrings.add(sb.toString());
}
}
// BFS 找到最小的非子串
Queue<String> queue = new LinkedList<>();
queue.offer("");
while (!queue.isEmpty()) {
String current = queue.poll();
for (char c = 'a'; c <= 'z'; c++) {
String next = current + c;
if (!subStrings.contains(next)) {
System.out.println(next);
return;
}
queue.offer(next); // 继续尝试更长的字符串
}
}
}
}
4、表演队
三八妇女节当天,蓝桥学院为了感恩母亲,决定组织一支由女同学组成的表演队。学院共有 N 位女同学,每位同学都有一个独特的表演能力值,分别为A1,A2,…,AN。学院需要从这 N 位同学中挑选出 K 位,组成一支表演队。
根据《表演队组建指南》,一支表演队的“差异值”定义为:队伍中所有同学的表演能力值之间的绝对差的总和。更正式地说,如果选出的 KK 位同学的表演能力值为 S1,S2,…,SK,那么差异值计算公式为:
现在,你的任务是帮助学院组建一只差异值最小的表演队,你只需要求出队伍的最小差异值即可。
输入格式:
第一行包含两个整数 N 和 K(1≤K≤N≤105),分别表示女同学的总数和需要挑选的同学数量。
第二行包含 N 个空格分隔的整数 A1,A2,…,AN(1 ≤ Ai ≤ 106),表示每位同学的表演能力值。
输出格式:
输出一个整数,表示选出的 K 位同学的最小差异值。
解题代码:
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int K = scanner.nextInt();
int[] A = new int[N];
for (int i = 0; i < N; i++) {
A[i] = scanner.nextInt();
}
scanner.close();
// 1. 排序
Arrays.sort(A);
// 前缀和数组,表示前i个元素的和
long[] fixsum = new long[N + 1];
// 前缀乘位置和数组,表示前i个元素乘以其下标的和
long[] mulSum = new long[N + 1];
for (int i = 0; i < N; i++) {
fixsum[i + 1] = fixsum[i] + A[i];
mulSum[i + 1] = mulSum[i] + (long) A[i] * i;
}
// 2. 计算最小差异值
long minDifference = Long.MAX_VALUE;
// 遍历所有可能的连续K个元素的窗口
for (int i = 0; i <= N - K; i++) {
int j = i + K - 1; // 窗口结束下标
// 计算当前窗口的差异值
long sumMul = mulSum[j + 1] - mulSum[i];
long sum = fixsum[j + 1] - fixsum[i];
long currentDiff = 2 * sumMul - (i + j) * sum;
if (currentDiff < minDifference) {
minDifference = currentDiff;
}
}
// 输出最小差异值
System.out.println(minDifference);
}
}
5、花束搭配
为了庆祝三八妇女节,花店推出了“双花搭配”活动。花店中有 n 种鲜花,每种鲜花有两种属性:
- 放在花束外部时,艳丽度为 Ai;
- 放在花束内部时,艳丽度为 Bi。
一束花需要由两种 不同的 鲜花组成,一种放在外部,另一种放在内部。如果一束花的“外部艳丽度之和”大于“内部艳丽度之和”,即满足 Ai+Aj > Bi+Bj,则这束花被认为是“完美搭配方案”。
现在,给定 n 种鲜花的艳丽度数组 A 和 B,请你帮助计算有多少种“完美搭配方案”。
注意,(i,j) 和 (j,i) 被视为不同的组合。
输入格式:
第一行包含一个整数 n(1≤n≤2×105),表示鲜花的种类数。
第二行包含 n 个整数 A1,A2,…,An(1≤ Ai ≤109),表示每种鲜花放在外部的艳丽度。
第三行包含 n 个整数 B1,B2,…,Bn(1≤ Bi ≤109),表示每种鲜花放在内部的艳丽度。
输出格式:
输出一个整数,表示“完美搭配方案”的数量。
解题代码:
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();// 鲜花种类
long []arr=new long[n];// A鲜花的艳丽度
long []brr=new long[n];// B鲜花的艳丽度
for (int i = 0; i < n; i++) {
arr[i]=sc.nextLong();
}
for (int i = 0; i < n; i++) {
brr[i]=sc.nextLong();
}
long[]sum=new long[n]; // AB两种鲜花的艳丽度值差A-B
for (int i = 0; i < n; i++){
sum[i]=arr[i]-brr[i];
}
Arrays.sort(sum);
int zuo=0; // 左边的索引
int you=n-1; // 右边的索引
long daan=0; // 存储当前符合的方案数
/**
* 初始化两个指针 left 和 right 分别指向 diff 数组的起始和末尾位置。
* 在 while 循环中,根据 diff[left] + diff[right] 的值进行判断和操作。
* 如果和大于 0,则将 right - left 的值累加到 ans 中,并将 right 指针左移一位;
* 如果和不大于 0,则将 left 指针右移一位。
*/
while (zuo<you) {
if(sum[you]+sum[zuo]>0){
// 因为sum是从小到大,所以如果sum[you]+sum[zuo]>0的话
// 那么sum[zuo]+sum[大于you的索引]全都符合相加大于0
daan+=you-zuo;
// 更新you 表示用下一个去检验
you--;
}else {
// 说明不符合,所以要增大zuo这样sun[zuo]才会大
// 才可能使sum[you]+sum[zuo]>0
zuo++;
}
}
// 最后记得daan*2因为 (j,i)和(j,i) 被视为不同的组合。
System.out.println(daan*2);
}
}
6、妇女唇膏
三月八日妇女节当天,蓝桥学院的姐妹团举办了一场“口红配唇膏”活动。她们带来了 N 支口红,每支口红拥有独特的色号,分别为 A1,A2,…,AN。活动的目标是为所有这些口红调制出一款统一的唇膏,其色号为 B,使得每支口红与这款唇膏搭配后都能呈现出最佳的美妆效果。
根据《美妆秘籍》的指引,姐妹们了解到,只有当口红的色号 A 与唇膏的色号 B 满足等式 A+B=A⊕B 时,二者混合后的色彩效果才能达到巅峰。因此,要实现活动目标,对于每一支口红 Ai(其中 i=1,2,…,N),唇膏的色号 B 都必须满足 Ai+B=Ai⊕B。
现在,你的任务是帮助姐妹找出一个最小的正整数 B,使得每一支口红 Ai 与该唇膏搭配后都能达到最佳效果。
输入格式:
第一行包含一个整数 N(1≤N≤105),表示口红的数量。
第二行包含 N 个空格分隔的整数 A1,A2,…,AN(1≤ Ai ≤109),表示每支口红的色号。
输出格式:
输出一个整数,表示满足条件的最小正整数 B。
解题代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
String S = scanner.next();
scanner.close();
int[] distances = new int[n];
int lastOne = -1;
// 从左向右扫描,计算距离最近的左边的 `1`
for (int i = 0; i < n; i++) {
if (S.charAt(i) == '1') {
lastOne = i;
} else if (lastOne != -1) {
distances[i] = i - lastOne;
} else {
distances[i] = Integer.MAX_VALUE; // 先赋个大值,等会再取最小
}
}
// 从右向左扫描,计算距离最近的右边的 `1`
lastOne = -1;
for (int i = n - 1; i >= 0; i--) {
if (S.charAt(i) == '1') {
lastOne = i;
} else if (lastOne != -1) {
distances[i] = Math.min(distances[i], lastOne - i);
} else if (distances[i] == Integer.MAX_VALUE) {
distances[i] = -1; // 左右都没 `1`
}
}
// 只输出 `0` 的位置对应的距离
boolean first = true;
for (int i = 0; i < n; i++) {
if (S.charAt(i) == '0') {
if (!first) System.out.print(" ");
System.out.print(distances[i]);
first = false;
}
}
}
}
有帮助的话,希望可以点赞❤️+收藏⭐,谢谢各位大佬~~✨️✨️✨️