算法刷题整理合集(三)·【算法赛】

在这里插入图片描述

本篇博客旨在记录自已的算法刷题练习成长,里面注有详细的代码注释以及和个人的思路想法,希望可以给同道之人些许帮助。本人也是算法小白,水平有限,如果文章中有什么错误或遗漏之处,望各位可以在评论区指正出来,各位共勉💪。

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 的二进制字符串 S1 表示当前服务点有志愿者,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,那么差异值计算公式为:

在这里插入图片描述

现在,你的任务是帮助学院组建一只差异值最小的表演队,你只需要求出队伍的最小差异值即可。

输入格式:

第一行包含两个整数 NK(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 种鲜花的艳丽度数组 AB,请你帮助计算有多少种“完美搭配方案”。

注意,(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;
            }
        }
    }
}

有帮助的话,希望可以点赞❤️+收藏⭐,谢谢各位大佬~~✨️✨️✨️

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乌云暮年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值