算法刷题整理合集(二)

news2025/3/16 5:12:18

在这里插入图片描述

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

文章目录

      • 1、区间移位
      • 2、扫雷Ⅱ
      • 3、分布式队列
      • 4、砍柴
      • 5、排列序数
      • 6、数位递增的数

1、区间移位

数轴上有几 个闭区间:D1,··D”。

其中区间 Di 用一对整数 [ai,bi] 来描述,满足 ai <= bi。

已知这些区间的长度之和至少有 10^4。

所以,通过适当的移动这些区间,你总可以使得他们的"并"覆盖 [0,10^4],就是说 [0,10^4]这个区间内的每一个点都落于至少一个区间内。

你希望找一个移动方法,使得位移差最大的那个区间的位移量最小。

具体来说,假设你将 Di 移动到 [ai + ci,bi + ci] 这个位置。你希望使得 max |ci|最小。

用例规模: 1 ≤ n ≤ 10^4,0 ≤ ai < bi < 10^4。

解题代码:

import java.util.*;

public class Main {
    private static int[][] intervals;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        intervals = new int[n][2];
        for (int i = 0; i < n; ++i) {
            // 将区间长度翻倍,结果除2
            intervals[i][0] = 2*sc.nextInt();
            intervals[i][1] = 2*sc.nextInt();
        }
        sc.close();
        // 将二维数组进行升序排列
        Arrays.sort(intervals, Comparator.comparingInt(i -> i[1]));

        int left = 0, right = (int)2e4;
        while (left < right){ // 二分查找,左闭右开
            int mid = (left + right) >> 1;
            if (check(mid)) right = mid;
            else left = mid + 1;
        }
        // 不是整数,输出带小数
        if (right % 2 == 0) System.out.println(right/2);
        else System.out.println((double)right/2);
    }

    private static boolean check(int shift){
        int cover = 0;
        List<int[]> temp = new ArrayList<>(Arrays.asList(intervals)); // 逐个遍历,并排除掉合格的区间
        while (true) {
            boolean qualified = false;
            for (int i = 0; i < temp.size(); ++i) {
                int[] interval = temp.get(i);
                if (interval[0] - shift <= cover /* 此时的cover可以理解为前一个区间的覆盖范围,这里检测的是向左移动能不能够到前面的 */ && interval[1] + shift >= cover /* 区间最右点达到的位置不超过区间的最大右偏移量 */) {
                    qualified = true;
                    int len = interval[1] - interval[0];
                    if (interval[0] + shift >= cover) cover += len; // 如果当前区间左移后超过前面区间的覆盖范围,那么此次移动,覆盖范围最多只能增加当前区间本身的长度,否则不连续
                    else cover = interval[1] + shift; // 若不能超过,覆盖范围最多是当前区间末端+位移量
                    temp.remove(i);
                    break; // 删除后立刻到下一个循环,以免Concurrent Modification Exception(贪心循环外面套一个while true的原因)
                }
            }
            if (!qualified || cover >= 2e4) break;
        }
        return cover >= 2e4;
    }
}

2、扫雷Ⅱ

在这里插入图片描述

规则如下。

  1. 地图为 n x m 的矩阵。
  2. 地图中包含地雷和数字。
  3. 如果某个点是地雷块,那么用 x表示。
  4. 如果某个点是数字块,那么用 0~8 表示,具体的数值为该点周围地雷的数量(最少为0个,最多为8个)。
  5. 如果某个点未知,即可能是地雷或者数字,我们用 * 表示。

周围: 对于(x,y)点来说,周围为(x-1,y),(x + 1,y),(x,y-1),(x,y+ 1),(x-1,y-1),(x-1,y+1),(x+1,y-1),( x+1,y+ 1)八个位置。需要注意的是,超过边界的点不能算作周围的点。

小蓝是扫雷高手,于是他在原来扫雷游戏的基础上改动了一下。

现在给定你一个3 x m 的地图,其中第二行全部都不是地雷,第一行和第三行都是未知,小蓝将第二行的数字全部告诉你,请问这幅地图有多少种不同的可能?

也就是说,假设每个格子有 10 种情况(x或者0~ 8),那么3 x m的地图总共有 10^3m 情况,请你找出满足以下两个要求的地图数量:

  1. 地图合法,即满足扫雷规则。

  2. 第二行与给定第二行的值相同,

答案可能很大,请对 998244353 取模。

用例规模: 1 <= n <= 5*10^5,0 <= pi <= 8。

解题代码:

import java.util.Scanner;

public class Main {
    static int N = (int)5e5+10,mod = 998244353;
    static int n;
    static int[][][] f =new int[N][3][3]; //i,j,k: 处理到第i列,第i列的地雷情况j和第i+1列地雷情况k
    static int[] p = new int[N]; // 每列地雷数

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt(); // 读取列数
        if (n == 1){
            int x = sc.nextInt();
            if (x == 0||x == 2) System.out.println(1);
            else System.out.println(2);
            return;
        }
        for (int i = 1; i <= n; i++) {
            p[i] = sc.nextInt();
        }
        // 处理第1列所有情况
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (i+j==p[1]){
                    f[1][i][j] = 1;
                }
                if (i == 1){
                    f[1][i][j] *= 2; //当该列地雷数量为1,可以有上下两种情况,故*2
                }
                if (j == 1) {
                    f[1][i][j] *= 2;
                }
            }
        }

        // 由第i列(已知)递推第i+1列(未知)DP
        for (int i = 1; i < n; i++) {
            for (int j = 0; j < 3; j++) {
                for (int k = 0; k < 3; k++) {
                    int next = p[i+1]-j-k; // next为第i+2列地雷情况
                    if (next >= 0&&next <= 2){
                        f[i+1][k][next] = (f[i+1][k][next] + f[i][j][k])%mod;
                    }
                    if (next == 1){
                        f[i+1][k][next] = (f[i+1][k][next]*2)%mod;
                    }
                }
            }
        }

        // 只要递推到n-1即可,判断n-1列的地雷情况是否满足第n列地雷数量
        int res = 0;
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (i+j==p[n]){
                    res = (res+f[n-1][i][j])%mod;
                }
            }
        }
        System.out.println(res);
    }
}

3、分布式队列

小蓝最近学习了一种神奇的队列:分布式队列。简单来说,分布式队列包含 N个节点(编号为0至N-1,其中0号为主节点),其中只有一个主节点,其余为副节点。

主/副节点中都各自维护着一个队列,当往分布式队列中添加元素时都是由主节点完成的(每次都会添加元素到主节点对应的队列的尾部);副节点只负责同步主节点中的队列。可以认为主/副节点中的队列是一个长度无限的一维数组,下标为 0,1,2.3…,同时副节点中的元素的同步顺序和主节点中的元素添加顺序保持一致。

由于副本的同步速度各异,因此为了保障数据的一致性,元素添加到主节点后,需要同步到所有的副节点后,才具有可见性。

给出一个分布式队列的运行状态,所有的操作都按输入顺序执行。你需要回答在某个时刻,队列中有多少个元素具有可见性。

输入格式:

第一行包含一个整数 NN,表示节点个数。

接下来包含多行输入,每一行包含一个操作,操作类型共有以下三种: add、sync 和 query,各自的输入格式如下:

  1. add:element: 表示这是一个添加操作,将元素 element 添加到队列中;
  2. sync followerid: 表示这是一个同步操作,followerid 号副节点会从主节点中同步下一个自己缺失的元素;
  3. query: 查询操作,询问当前分布式队列中有多少个元素具有可见性。

输出格式:

对于每一个 query 操作,输出一行,包含一个整数表示答案。

用例规模:
对于 30% 的评测用例:1 ≤ 输入的操作数 ≤ 100。

对于 100% 的评测用例:1 ≤ 输入的操作数 ≤ 2000,1 ≤ N ≤ 10,1 < followerid ≤ N,0 ≤ element ≤ 10^5。

解题代码:

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        // 用于装下主节点和副节点,长度为n
        ArrayList<List<Long>> list = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            list.add(new ArrayList<>());
        }
        while (sc.hasNext()){
            // 获取输入的操作
            String cao = sc.next();
            switch (cao) {
                case "add":
                    long element = sc.nextLong();
                    List<Long> headQueue = list.get(0);
                    headQueue.add(element);
                    break;
                case "sync":
                    int queueIndex = sc.nextInt(); // 需要同步的队列
                    syncData(list.get(0), list.get(queueIndex));
                case "query":
                    // 由于队列式是有序的同步数据,我们只需要获取最凶阿德队列的长度即可
                    int len = list.get(0).size(); // 初始化为最大个数,即头节点拥有元素的个数
                    for (int j = 1; j < list.size(); j++) {
                        len = Math.min(list.get(j).size(), len);
                    }
                    System.out.println(len);
                    break;
            }
        }
        sc.close();
    }

    public static void syncData(List<Long> headQueue, List<Long> fuQueue) {
        // 检查出缺失的元素,无需便利判断(副节点与头节点要么完全相等,要么差数据,并不会存在元素不相等的情况)
        if (headQueue.size() != fuQueue.size()){
            int lackIndex = fuQueue.size() % headQueue.size(); // 利用取模运算,可以得到所缺数据的第一个索引
            fuQueue.add(headQueue.get(lackIndex)); // 将头结点这个数据添加到副节点即可
        }
    }
}

4、砍柴

小蓝和小乔正在森林里砍柴,它们有 T 根长度分别为 n1,n2,⋯,nT 的木头。对于每个初始长度为 n 的木头,小蓝和小乔准备进行交替砍柴,小蓝先出手。

每次砍柴时,若当前木头长度为 x,需要砍下一截长度为 p 的木头,然后换另一个人继续砍,其中 2 ≤pxp 必须为质数。当轮到某一方时 x=1 或 x=0,它就没法继续砍柴,它就输了。它们会使用最优策略进行砍柴。请对每根木头判断是小蓝赢还是小乔赢,如果小蓝赢请输出 1(数字 1),如果小乔赢请输出 0(数字 0)。

用例规模:

对于 20% 的评测用例,1 ≤ ni ≤ 10^3;

对于所有评测用例,1 ≤ ni ≤ 10^5,1 ≤ T ≤ 10^4。

解题代码:

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        //先打表列出所有的质数
        List<Integer> a=new ArrayList<>();//存2-100000之间的质数
        for (int i = 2; i <=100000; i++) {
            boolean isright=true;
            for (int j = 2; j*j <=i; j++) {
                if(i%j==0) {
                    isright =false;
                    break;
                }
            }
            if(isright) {
                a.add(i);
            }
        }
        //动态规划
        int dp[]=new int[100001];//当前状态先手赢为1否则为0
        dp[2]=1;
        for (int i = 2; i <=100000; i++) {
            for (int j = 0; j < a.size(); j++) {
                int x=i-a.get(j);//当次砍的长度
                if(x<0) {
                    //防止出现柴长度只有1砍了2的情况,也就是防止超砍情况
                    break;
                }
                if(dp[x]==0) {
                    //说明下一个人来砍必输,所有他赢了,后面就不用循环了,因为他们砍柴采用最优策略
                    dp[i]=1;
                    break;
                }
            }
        }
        int T=sc.nextInt();//测试的组数
        int []trr=new int[T];//值用来存输赢

        for (int i = 0; i < T; i++) {
            int t=sc.nextInt();
            trr[i]=dp[t]==1?1:0;//因为上面动态规划已经模拟了所有情况所以这里直接根据上面动态规划判断即可
        }
        for (int i = 0; i < T; i++) {
            System.out.println(trr[i]);
        }
    }
}

5、排列序数

如果用 a b c d 这4个字母组成一个串,有 4!=24 种,如果把它们排个序,每个串都对应一个序号:

abcd 0
abdc 1
acbd 2
acdb 3
adbc 4
adcb 5
bacd 6
badc 7
bcad 8
bcda 9
bdac 10
bdca 11
cabd 12
cadb 13
cbad 14

cbda 15
cdab 16
cdba 17
现在有不多于 10 个两两不同的小写字母,给出它们组成的串,你能求出该串在所有排列中的序号吗?

输入描述:

输入一行,一个串。

输出描述:

输出一行,一个整数,表示该串在其字母所有排列生成的串中的序号。注意:最小的序号是 0。

解题代码:

import java.util.Scanner;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {

    static public List<String> list=new ArrayList<>();

    public static void main(String[] args) {
        Scanner scan=new Scanner(System.in);
        String s=scan.next();
        char[] ch=s.toCharArray();//把字符串转换成数组字符
        f(ch,0,s.length()-1);
        Collections.sort(list);//排列
        for (String s1 : list) {
            if(s1.equals(s))//遍历集合匹配
            {
                System.out.println(list.indexOf(s1));
                break;
            }
        }
    }
    //全排列,列出所有情况
    public static void f(char[] ch, int l, int r)
    {
        if (l==r)
        {
            list.add(String.valueOf(ch));
        }
        else {
            for (int i = l; i <= r; i++) {
                swap(ch, l, i);
                f(ch, l + 1, r);
                swap(ch, l, i);
            }
        }
    }

    public static void swap(char[] ch,int i,int j)
    {
        char temp=ch[i];
        ch[i]=ch[j];
        ch[j]=temp;
    }
}

6、数位递增的数

一个正整数如果任何一个数位不大于右边相邻的数位,则称为一个数位递增的数。

例如 1135 是一个数位递增的数,而 1024 不是一个数位递增的数。

给定正整数 n,请问在整数1至 n 中有多少个数位递增的数?

输入描述:

输入的第一行包含一个整数 n(1<n<10^6)。

输出描述:

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

解题代码:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int count = 0;
        sc.close();
        for (int i = 11; i <= n; i++) {
            // 将数字转换为一个个字符
            String before = Integer.toString(i);
            char[] c = before.toCharArray();
            // 进行排序
            Arrays.sort(c);
            String ans = "";
            // 将字符排序后再添加排列
            for (int j = 0; j < c.length; j++) {
                ans += c[j];
            }
            // 将原始数据和排序后的对比,不同的则不为递增数
            if (before.equals(ans)){
                count++;
            }
        }
        System.out.println(count);
    }
}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2315794.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32配套程序接线图

1 工程模板 2 LED闪烁 3LED流水灯 4蜂鸣器 5按键控制LED 6光敏传感器控制蜂鸣器 7OLED显示屏 8对射式红外传感器计次 9旋转编码器计次 10 定时器定时中断 11定时器外部时钟 12PWM驱动LED呼吸灯 13 PWM驱动舵机 14 PWM驱动直流电机 15输入捕获模式测频率 16PWMI模式测频率占空…

Houdini学习笔记

1. Houdini中一次只能显示一个物体 如果要都显示 需要 merge 节点 粉色的是 以参考显示 2.对任意一个节点按F1 可以弹出houdini官方文档 3. 恢复视角 Space H,居中 Space G 居中选中物体

仿Ant Design Vue风格自定义浏览器滚动条样式

仿Ant Design Vue风格自定义浏览器滚动条样式 问题原因 浏览器默认的滚动条样式很丑&#xff0c;无法满足需求&#xff0c;需要自定义滚动条样式&#xff0c;参考ant-design-vue的样式 css修改滚动相关属性可查阅官方文档 选择器介绍 ::webkit-scrollbar&#xff1a;滚动条…

单元测试、系统测试、集成测试、回归测试的步骤、优点、缺点、注意点梳理说明

单元测试、系统测试、集成测试、回归测试的梳理说明 单元测试 步骤&#xff1a; 编写测试用例&#xff0c;覆盖代码的各个分支和边界条件。使用测试框架&#xff08;如JUnit、NUnit&#xff09;执行测试。检查测试结果&#xff0c;确保代码按预期运行。修复发现的缺陷并重新测…

网络安全反渗透 网络安全攻防渗透

网络渗透防范主要从两个方面来进行防范&#xff0c;一方面是从思想意识上进行防范&#xff0c;另一方面就是从技术方面来进行防范。 1.从思想意识上防范渗透 网络攻击与网络安全防御是正反两个方面&#xff0c;纵观容易出现网络安全事故或者事件的公司和个人&#xff0c;在这些…

《GitHub网路访问不稳定:解决办法》:此文为AI自动生成

《GitHub网路访问不稳定&#xff1a;解决办法》&#xff1a;此文为AI自动生成 GitHub 网路访问不稳定初现 在当今数字化时代&#xff0c;软件开发行业蓬勃发展&#xff0c;GitHub 作为全球最大的代码托管平台&#xff0c;已然成为无数开发者不可或缺的 “宝库”。它不仅汇聚了…

G-Star 公益行 | 温暖相约 3.30 上海「开源×AI 赋能公益」Meetup

你是否曾想过&#xff0c;在这个数字化浪潮席卷的时代&#xff0c;公益组织如何突破技术瓶颈&#xff1f;当 AI 成为热门话题&#xff0c;它能为公益事业带来怎样的温度&#xff1f;开源的力量&#xff0c;如何让每一份善意都拥有无限可能&#xff1f; G-Star 公益行&#xff…

docker pull 镜像问题

问题一&#xff1a;pull镜像报错:time out 分析&#xff1a;源问题&#xff0c;网络不稳定&#xff0c;更换加速源&#xff0c;地址&#xff1a;/etc/docker/daemon.json 解决&#xff1a;更换地址&#xff0c;如下&#xff0c;然后敲&#xff1a;docker daemon-reload &&…

STAR Decomposition 一种针对极端事件的信号分解方法 论文精读加复现

STAR 分解&#x1f680; 在时序预测任务中&#xff0c;为了情绪化信号的各种成分&#xff0c;例如趋势信息季节信息等往往都需要对信号进行分解。目前熟知的分解方式有很多种&#xff0c;经验模态分解 EMD 变分模态分解 VMD &#xff0c;还有 集合经验模态分解 EEMD&#xff0c…

基于SpringBoot + Vue 的房屋租赁系统

基于springboot的房屋租赁管理系统-带万字文档 SpringBootVue房屋租赁管理系统 送文档 本项目有前台和后台两部分、多角色模块、不同角色权限不一样 共分三种角色&#xff1a;用户、管理员、房东 管理员&#xff1a;个人中心、房屋类型管理、房屋信息管理、预约看房管理、合…

Excel中国式排名,3种方法!

大家好&#xff0c;我是小鱼。 什么是中国式排名呢&#xff1f; 举个例子比如说公司一共有10名员工进行成绩考核&#xff0c;如果9个人考核成绩都是90分&#xff0c;你是89分&#xff0c;按照国际惯用的排名法则&#xff1a;9 个人考核成绩并列第一&#xff0c;你第10名&…

Flutter:跑马灯公告栏

组件 import dart:async; import package:flutter/material.dart; import package:ducafe_ui_core/ducafe_ui_core.dart;class MarqueeNotice extends StatefulWidget {/// 公告数据列表&#xff0c;每条公告包含title和descfinal List<Map<String, String>> notic…

Jmeter下载及环境配置

Jmeter下载及环境配置 java环境变量配置配置jdk环境变量检查是否配置成功JMeter下载 java环境变量配置 访问地址&#xff1a; https://www.oracle.com/cn/java/technologies/downloads/ 注意&#xff1a;需要自己注册账号 下载完成&#xff0c;解压后的目录为&#xff1a; …

【初级篇】如何使用DeepSeek和Dify构建高效的企业级智能客服系统

在当今数字化时代,企业面临着日益增长的客户服务需求。使用Dify创建智能客服不仅能够提升客户体验,还能显著提高企业的运营效率。关于DIfy的安装部署,大家可以参考之前的文章: 【入门级篇】Dify安装+DeepSeek模型配置保姆级教程_mindie dify deepseek-CSDN博客 AI智能客服…

微信小程序threejs三维开发

微信小程序threejs开发 import * as THREE from three; const { performance, document, window, HTMLCanvasElement, requestAnimationFrame, cancelAnimationFrame, core, Event, Event0 } THREE .DHTML import Stats from three/examples/jsm/libs/stats.module.js; im…

大数据-spark3.5安装部署之standalone模式

真实工作中还是要将应用提交到集群中去执行&#xff0c;Standalone模式就是使用Spark自身节点运行的集群模式&#xff0c;体现了经典的master-slave模式。集群共三台机器&#xff0c;具体如下 u22server4spark&#xff1a; master worker u22server4spark2&#xff1a; worke…

技术视界|构建理想仿真平台,加速机器人智能化落地

在近期的 OpenLoong 线下技术分享会 上&#xff0c;松应科技联合创始人张小波进行了精彩的演讲&#xff0c;深入探讨了仿真技术在机器人智能化发展中的关键作用。他结合行业趋势&#xff0c;剖析了现有仿真平台的挑战&#xff0c;并描绘了未来理想仿真系统的设计理念与实现路径…

AutoGen多角色、多用户、多智能体对话系统

2023-03-11-AutoGen 使用【autoGenchainlitdeepSeek】实现【多角色、多用户、多智能体对话系统】 1-核心思路 01&#xff09;技术要点&#xff1a;autoGenchainlitdeepSeek02&#xff09;什么是autoGen->autogen是微软旗下的多智能体的框架03&#xff09;什么是chainlit-&g…

SQL99 多表查询

内连接&#xff1a; select name, depart_name, city from employee e join department d on e.depart_id d.depart_id join location l on d.locat_id l.locat_id; 外连接 注&#xff1a;本图取自博客园大佬"anliux"的博客&#xff0c;原帖链接&#xff1a;【学…

sql靶场5-6关(报错注入)保姆级教程

目录 sql靶场5-6关&#xff08;报错注入&#xff09;保姆级教程 1.第五关 1.步骤一&#xff08;闭合&#xff09; 2.步骤二&#xff08;列数&#xff09; 3.报错注入深解 4.报错注入格式 5.步骤三&#xff08;数据库表名&#xff09; 6.常用函数 7.步骤四&#xff08;表…