基础算法学习

news2024/11/20 1:40:37

文章目录

    • 快速排序
    • 归并排序
    • 二分
      • 浮点数二分
    • 高精度
      • BigInteger
      • BigDecimal
    • 前缀和
    • 差分
    • 双指针
    • 位运算
    • 离散化
    • 区间合并

快速排序

  1. 确定分界点x (可以是左边界,右边界,中间随机)
  2. 将小于等于x的数放到左边,大于等于x的放右边
  3. 递归处理左右两端

如何处理第二步:

双指针法

模版:

public static void quickSort(int[]arr,int l,int r) {
    if(l >= r) {
        return;
    }
    int x= arr[l+r>>1];   //arr[l+r+1>>1] 后面递归要用i
    int i = l - 1;  //初始左指针位置
    int j = r + 1;  //初始右指针位置
    while(j > i) {
        do i++; while(arr[i] < x);   //先将左指针向右移,在判断底下这个数是不是小于x的,是就继续右移
        do j--; while(arr[j] > x);   //先将右指针向左移,再判断底下这个数是否大于x,是就继续左移
        if(j > i) swap(arr[i],arr[j]); //只有在下标满足条件的情况下才交换
    }
        
    quickSort(arr,l,j);   //这里递归的边界取i还是j,与x取右边界还是左边界有关
    quickSort(arr,j + 1,r); //x如果取的左边界,所以递归边界一定要用j,反之,一定要用i
    /*
     *quickSort(arr,l,i - 1);
      quickSort(arr,i,r);
     */
}

最后结果可能是 i = j j < i

归并排序

  1. 以数组下标中间点为分界点
  2. 递归排序左边和右边
  3. 归并,合二为一

如何将这两个有序的序列合二为一:

双指针法:

直到有一条序列 到了底,没到底的序列剩下那部分直接接在结果序列后面即可

时间复杂度:nlog(n)

总共有logn层,每层时间复杂度都是On的,所以总时间复杂度为nlogn、

快排同理,虽然每次不一定是平分的,但是期望是平分的

模版:

public static void merageSort(int[]a,int l,int r) {
         if(l >= r) return;
         int mid = l + ((r - l) >> 1);
         merageSort(a,l,mid);
         merageSort(a,mid+1,r);
         int[]temp = new int[r - l + 1];
         int k = 0;  //记录temp数组的元素
         int i = l;  //第一条序列开始的指针
         int j = mid + 1; //第二条序列开始的指针
         while(i <= mid && j <= r) {
             if(a[i] <= a[j]) temp[k++] = a[i++];
             else temp[k++] = a[j++];
         }
         //两指针谁没走到头,就继续将剩下的接在temp后面
         while(i <= mid) temp[k++] = a[i++];
         while(j <= r) temp[k++] = a[j++];
         //最后将得到的排好序的数组赋值给原来的
         for(i = l,j = 0;i <= r;i++,j++) {
             a[i] = temp[j];
         }
}

二分

模版:

while(l < r) {
    int mid = l + r >> 1;
    if(check(mid)) r = mid;
    else l = mid + 1;
}

while(l < r) {
    int mid = l + r + 1 >> 1;
    if(check(mid)) l = mid;
    else r = mid - 1;
}

先根据check函数判断处理结果是什么,再根据处理结果判断mid是否要补充加1

这里l 和 r最后结果都是一样的

浮点数二分

不需要考虑边界问题

public class Main{
    public static void main(String[]args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        double f = Double.parseDouble(br.readLine());
        double l = 0;
        double r = Math.abs(f);
        //如果要保留4位小数,写1e-6  保留5位 1e-7  经验值  比要求的多两位
        //这里也可以不管就直接循环100次来代替用精度表示的迭代
        while(r - l >= 1e-8) {
            double mid = (l + r) / 2;
            if(mid * mid * mid >= Math.abs(f)) r = mid;
            else l = mid;
        }
        
        if(f >= 0) System.out.println(String.format("%.6f",r));
        else System.out.println("-"+String.format("%.6f",r));
    }
}

高精度

超过int的值 10的九次方

超过long的值 10的18次方

BigInteger

public BigInteger(int num,Random rnd)  //获取随机大整数,范围0~ 2的num次方-1
public BigInteger(Stirng val)
public BigInteger(String val,int radix)  //获取指定进制大整数

public static BigInteger valueOf(long val)  //内部有优化,但超过long范围就不行了
    //在内部对-16~16提前创建好了对象

对象一旦创建不能被改变,如果进行add,等操作,会产生新的BigInteger对象记录

add
subtract
multiply
divide   #除法,获取商
divideAndRemainder(BigInteger val)  #除法,获取商和余数,放在一个数组中返回
pow(int e) #次幂
max/min(BigInteger val)
intValue(BigInteger val) #转成int类型数据,超出范围数据有误

BigDecimal

public BigDecimal(double val)
public BigDecimal(String val)

public static BigDecimal valueOf()
# 对于0~10之间的整数,包含0 10 ,方法会返回已经创建好的对象,不会重新new
add
subtract
multiply
divide
BigDecimal divide(BigDecimal val,精确几位,舍入模式)
#舍入模式
四舍五入:RoundingMode.HALF_UP
其他在RoundingMode类中找即可

前缀和

就是再定义一个长度和要存放数据的数组(a)等长的数组(s),在初始化存放数据数组时,将这个数组也初始化,每个位置存放前一个位置(s[i - 1])和 a[i] 的和

其中a数组和s数组下标最好都从1开始,这样在初始化前缀和数组时,是s[i] = s[i - 1] + a[i] 这里的i - 1,就不用单独判断

差分

差分就是前缀和的逆运算,

作用:

可以用O1的时间复杂度,给原数组某个区间加上一个固定的值

处理:

如果想让数组[l , r] 区间的数都加上c,那么让diff[l] + c , 让 diff[r + 1] - c 即可

核心:

构造差分数组不是核心,差分数组的构造可以看做,将元素一个一个按照规则添加进一个全为0的差分数组中,核心是添加进差分数组的规则

  • 一维差分

    /**
     * 要添加数的区间 1 ~ r
     * 要添加的值
     */
    public static void insert(int[]a,int l,int r,int c) {
        a[l] += c;
        a[r+1] -= c;
    }
    
  • 二维差分

    /**
     * 要添加数的区间 x1,y1  ~ x2,y2
     * 要添加的值  c
     */
    public static void insert(int[][]d,int x1,int y1,int x2,int y2,int c) {
        d[x1][y1] += c;
        d[x2 + 1][y1] -= c;
        d[x1][y2 + 1] -= c;
        d[x2 + 1][y2 + 1] += c;
    }
    

双指针

所有双指针算法都是On的

模板:

for(i = 0,j = 0;i < n;i++) {
    while(j < i && check(i,j)) j++;
    //每道题目具体逻辑
}

核心思想:

for(int i = 0;i < n;i++) {
    for(int j = 0;j < n;j++) {
    }
}
//O(n^2)

将上面的枚举i,枚举j,优化到On级别

位运算

x = 10 n = 1010 (二进制表现形式)

源码:0……01010

反码:1……10101

补码:反码+1 1……10110

  • 求n的二进制表示中第k位是几

    # 将n右移k位,再&1
    n >> k & 1
    
  • lowbit 操作:返回x的最后一位1,lowbit最高一位1,就是x最低一位1

    x & -x
    

    可以用来统计x中1的个数:每次将最后一个1去掉,减了几次就说明有几个1

离散化

在这里插入图片描述

基本含义:

对于值域较大,而个数相对较少的一组数据 a[ ] ,例如 值域 0~10^9 个数 :5

我们需要用到他的值作为下标,开一个10^9的数组显然不合理

所以我们需要将他映射到一个从0开始的连续的数组中(将他的值映射成下标),这个过程称为离散化

a[] 数组应该是有序的,整个过程要保序的进行

  • 其中a数组可能存在重复元素,需要去重
  • 如何算出a[i] 离散化后的值 (二分 找到第一个大于等于x的位置,即找右边界)

例题:

acwing:802 区间和

假定有一个无限长的数轴,数轴上每个坐标上的数都是 0。

现在,我们首先进行 n次操作,每次操作将某一位置 x 上的数加 c。

接下来,进行 m 次询问,每个询问包含两个整数 l 和 r,你需要求出在区间 [l,r] 之间的所有数的和。

输入格式
第一行包含两个整数 n和 m。

接下来 n行,每行包含两个整数 x和 c。

再接下来 m行,每行包含两个整数 l和 r。

输出格式

共 m行,每行输出一个询问中所求的区间内数字和。

数据范围

−10^9 ≤x≤ 10^9,
1≤n,m≤10^5,
−10^9≤ l ≤r ≤ 10^9,
−10000≤c≤10000

分析:

区间和这种题目对于数据量较少的可以直接使用前缀和,本题数据量较大,先进行离散化处理再使用前缀和

将需要用到的下标记录下来,将这些不连续的下标想办法映射成连续的数字(将这些下标排完序后返回下标对应索引即可,可以用indexOf,但是效率较低可能超时,最好用二分查找)

这里x的范围是 -10的九次方到10的九次方 ,而需要用到的下标数量最多为 n + 2m (添加的时候访问n次下标,询问的时候一次访问两个,就是2m)也就是30万,符合离散化的特性

区间合并

给多个区间,如果区间之间有交集的话,将他们合并成一个区间

处理方式:

先将所有区间以左端点从大到小排序,维护一个以st 开头,ed 结尾的区间 x,遍历所有区间

如果遍历到的区间 item,起始点大于x的ed,说明当前维护区间和后面的区间没有关系,合并完成一个区间,否则比较两区间的ed,将较大的那个作为当前维护区间的ed

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

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

相关文章

Intellij idea 内存不够用了,怎么处理?

目录 如何判断内存不够用了 下面演示一下如何开启内存指示器&#xff08;Memory Indicator&#xff09; 解决方案 第一种&#xff1a;双击"内存指示器(Mempory Indicator)" 第二种&#xff1a;增大Intellij Idea 最大可使用内存 如何判断内存不够用了 运行项目后…

ExoPlayer - Failed to initialize OMX.qcom.video.decoder.avc

人莫鉴于流水而鉴于止水&#xff0c;唯止能止众止 1. 背景 使用ExoPlayer&#xff0c;我不信你没遇到过这个问题&#xff1a; java.lang.IllegalArgumentException: Failed to initialize OMX.qcom.video.decoder.avc 详细内容如下图所示&#xff1a; 2. MediaCodec(解码器) …

渲染到纹理:原理及WebGL实现

这篇文章是WebGL系列的延续。 第一个是从基础知识开始的&#xff0c;上一个是向纹理提供数据。 如果你还没有阅读过这些内容&#xff0c;请先查看它们。 NSDT在线工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - …

快速入门opencv(python版)

Open Source Computer Vision Library。OpenCV是一个&#xff08;开源&#xff09;发行的跨平台计算机视觉库&#xff0c;可以运行在Linux、Windows和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C 类构成&#xff0c;同时提供了Python、Ruby、MATLAB等语言的…

PHP微信UI在线聊天系统源码 客服私有即时通讯系统 附安装教程

DuckChat是一套完整的私有即时通讯解决方案&#xff0c;包含服务器端程序和各种客户端程序&#xff08;包括iOS、Android、PC等&#xff09;。通过DuckChat&#xff0c;站点管理员可以快速在自己的服务器上建立私有的即时通讯服务&#xff0c;用户可以使用客户端连接至此服务器…

CAN网络出现错误帧从哪些方面去分析解决

标题&#xff1a;CAN网络出现错误帧从哪些方面去分析 实例1&#xff1a; 断电重启后&#xff0c;会有错误帧产生。 检查方案&#xff1a; 查看收发模块的初始化、使能是否在发送CAN报文之前完成&#xff1f; 实例2&#xff1a; 周期性报文&#xff0c;有时会冒出一帧错误帧&…

四则计算机实现(C++)(堆栈的应用)

算法要求&#xff1a; 输入一个数学表达式(假定表达式输入格式合法)&#xff0c;计算表达式结果并输出。数学表达式由单个数字和运算符“”、“-”、“*”、“/”、“(、) ”构成&#xff0c;例如 2 3 * ( 4 5 ) - 6 / 4。变量、输出采用整数&#xff0c;只舍不入。 图解算…

MySQL InnoDB Cluster

MySQL InnoDB Cluster 一、InnoDB Cluster 基本概述 MySQL InnoDB Cluster 为 MySQL 提供了一个完整的高可用解决方案。通过使用 MySQL Shell 提供的 AdminAPI,你可以轻松地配置和管理一组至少由3个MySQL服务器实例组成的 InnoDB 集群。 InnoDB 集群中的每个 MySQL 服务器实例…

linux无网络 无ip,显示网络未连接

标题:linux无网络 无ip&#xff0c;显示网络未连接 参考blog&#xff1a;Linux无网络连接问题排查 首先我们发现ens33没有ip地址&#xff0c;说明这个接口并没有被分到ip&#xff1b; 我们可以通过手动方式来给ens33获得网络ip sudo dhclient ens33&#xff0c;之后再输入ifc…

大数据Hadoop-HDFS_元数据持久化

大数据Hadoop-HDFS_元数据持久化 &#xff08;1&#xff09;在HDFS第一次格式化后&#xff0c;NameNode&#xff08;即图中的主NameNode&#xff09;就会生成fsimage和editslog两个文件&#xff1b; &#xff08;2&#xff09;备用NameNode&#xff08;即图中的备NameNode&…

ChatGPT Plus/GPT4高级数据分析和插件功能详解

ChatGPT 在论文写作与编程方面也具备强大的能力。无论是进行代码生成、错误调试还是解决编程难题&#xff0c;ChatGPT都能为您提供实用且高质量的建议和指导&#xff0c;提高编程效率和准确性。此外&#xff0c;ChatGPT是一位出色的合作伙伴&#xff0c;可以为您提供论文写作的…

微服务实战系列之Redis(cache)

前言 云淡天高&#xff0c;落木萧萧&#xff0c;一阵西北风掠过&#xff0c;似寒刀。冬天渐渐变得更名副其实了。“暖冬”的说法有点言过其实了。——碎碎念 微服务实战系列之Cache微服务实战系列之Nginx&#xff08;技巧篇&#xff09;微服务实战系列之Nginx微服务实战系列之F…

Structured Streaming: Apache Spark的流处理引擎

欢迎来到我们的技术博客&#xff01;今天&#xff0c;我们要探讨的主题是Apache Spark的一个核心组件——Structured Streaming。作为一个可扩展且容错的流处理引擎&#xff0c;Structured Streaming使得处理实时数据流变得更加高效和简便。 什么是Structured Streaming&#…

数据结构中的二分查找(折半查找)

二分法&#xff1a;顾名思义&#xff0c;把问题一分为2的处理&#xff0c;是一种常见的搜索算法&#xff0c;用于在有序数组或这有序列表中查找指定元素的位置&#xff0c;它的思想是将待搜索的区间不断二分&#xff0c;然后比较目标值与中间元素的大小关系&#xff0c;然后确定…

Failed to connect to gitee.com port 443: Time out 连接超时提示【Bug已完美解决-鸿蒙开发】

文章目录 项目场景:问题描述原因分析:解决方案:解决方案1解决方案2:解决方案3:此Bug解决方案总结解决方案总结**心得体会:解决连接超时问题的三种方案**项目场景: 导入Sample时遇到导入失败的情况,并提示“Failed to connect to gitee.com port 443: Time out”连接超…

实现一个通讯录

目录 项目要求及功能实现 通讯录的代码实现 contact.h: contanct.c main.c 项目要求及功能实现 1、可以存放100个人的信息 2、每个人的信息 名字 性别 年龄 电话 地址 3、增加联系人 4、删除指定联系人 5、查找指定联系人 6、修改指定联系人 7、显示联系人信息 8、排…

运维笔记111

运维笔记 Navicat中查询指定字段名所在的表名tomcat设置JVM的初始堆内存修改catalina.sh文件修改完保存并关闭tomcat启动tomcat 查询数据库连接数查询是否存在死锁 Navicat中查询指定字段名所在的表名 SELECT * FROM information_schema.COLUMNS WHERE COLUMN_NAME‘替换成你要…

Redis-Redis 高级数据结构 HyperLogLog与事务

Redis 高级数据结构 HyperLogLog HyperLogLog(Hyper [ˈhaɪpə(r)] ) 并不是一种新的数据结构 ( 实际类型为字符串类 型) &#xff0c;而是一种基数算法 , 通过 HyperLogLog 可以利用极小的内存空间完成独立总数的统计&#xff0c;数据集可以是 IP 、 Email 、 ID 等。 如…

【brew】Mac上安装vue3

先安装node。 这里我从其他博客找的方案&#xff0c;原始脚本下载太慢了。 cnpm的安装&#xff1a; 让npm更快一点。 npm install -g cnpm --registryhttps://registry.npm.taobao.org安装vue脚手架 2.0版本&#xff1a;sudo npm install -g vue-cli 3.0版本&#xff1a; sud…

对话式数据需求激增,景联文科技提供高质量多轮对话数据定制采集标注服务

大模型的快速发展使得数据服务需求激增&#xff0c;产品整体处于供不应求状态。对话式数据集成为当下需求热点&#xff0c;人们对于更复杂、更真实的多轮对话数据需求不断增加&#xff0c;定制化服务占据市场需求主流。 通过对多轮对话数据的训练&#xff0c;模型可以更好地理解…