AcWing算法基础课笔记 1.基础算法

news2024/12/23 12:09:16

目录

  • AcWing算法基础课笔记 1.基础算法
    • 二分排序
      • 基本思想
      • 代码
    • 归并排序
      • 基本思路
      • 代码
    • 高精度计算
      • 加法
      • 减法
      • 乘法
      • 除法
    • 前缀和
      • 一维
      • 二维

AcWing算法基础课笔记 1.基础算法

二分排序

基本思想

基于分治的思想

  1. 确定哨兵 x x x:可以取左边界,中间值,右边界,甚至是任意值;
  2. 分区间:让小于 x x x的值全都归到 x x x的左边,大于 x x x的值全都归到 x x x的右边;
  3. 递归处理左右两端直到整个序列有序

代码

这是严蔚敏版数据结构快排的代码,也是我我一直用的代码,不是y神的模板。

去打洛谷题会报TLE

#include <iostream>
using namespace std;

const int N = 100010;
int Array[N];

//分区间
int partition(int* array, int low, int high){
    int value = array[low];
    while(low < high){
        while(low < high && array[high] >= value) high--;
        array[low] = array[high];
        while(low < high && array[low] <= value) low++;
        array[high] = array[low];
    }
    array[low] = value;
    return low;
}

//递归处理
void quicksort(int* array, int low, int high){
    if(low < high){
        int newvalue = partition(array, low, high);
        quicksort(array, low, newvalue);
        quicksort(array, newvalue+1, high);
    }
}

int main(){
    int n;
    cin >> n;
    for(int i = 0; i < n; i++) cin >> Array[i];
    quicksort(Array, 0, n-1);
    for(int i = 0; i < n; i++) cout << Array[i] << " ";
    return 0;
}

归并排序

基本思路

基于分治的思想

  1. 确定分界点 m i d = ( l o w + h i g h ) / 2 mid = (low + high) / 2 mid=(low+high)/2
  2. 递归分解左右部分,直到不可再分
  3. 回溯归并

详细的思路讲解见归并排序详解:20分钟理解归并排序 ,讲的真的很好很好

代码

#include <iostream>
using namespace std;

const int N = 100010;
int Array[N],tmp[N];

void mergesort(int* array, int low, int high){
    if(low >= high) return;                   //数组没有元素或者只有一个元素时,直接返回
    int mid = (low + high) / 2;
    //递归分解左右部分,直到不可再分
    mergesort(array, low, mid);
    mergesort(array, mid + 1, high);

    int k = 0, i = low, j = mid + 1;
    //归并:合二为一
    while(i <= mid && j <= high){              //对每个分组进行排序
        if(array[i] <= array[j]) tmp[k++] = array[i++];
        else tmp[k++] = array[j++]; 
    }
    //将剩下来的数组元素直接加到数组后面
    while(i <= mid) tmp[k++] = array[i++];
    while(j <= high) tmp[k++] = array[j++];

    for(int i = low, j = 0; i <= high; i++ , j++) array[i] = tmp[j];
}

int main(){
    int n;
    cin >> n;
    for(int i = 0; i < n; i++) cin >> Array[i];
    mergesort(Array, 0, n-1);
    for(int i = 0; i < n; i++) cout << Array[i] << " ";
    return 0;
}

高精度计算

高精度计算即大整数的加减乘除,C++中没有表示大整数的类型,最长的long long也只有64位

而大整数指的是数字长度 ≤ 1 0 6 \leq 10^6 106,注意是长度,不是数值。而小整数指的是数值 ≤ 1 0 9 \leq 10^9 109

而在实际做题或者应用中,通常是这四种:

  • 两个大整数相加
  • 两个大整数相减
  • 一个大整数乘以一个小整数
  • 一个大整数除以一个小整数

大整数的存储:对于大整数通常用数组存储,从低位到高位存储比较方便。

加法

#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;

vector<int> add(vector<int>& A, vector<int>& B){
    vector<int> C;
    int t = 0;                //应该压入数组的每一位数值
    for(int i = 0; i < A.size() || i < B.size(); i++){
        if(i < A.size()) t += A[i];
        if(i < B.size()) t += B[i];        //每一位A[i]+B[i]+t
        C.emplace_back(t % 10);            //存储的是模10的值
        t = t / 10;                        //重新计算进位用于下一位的计算
    }
    if(t) C.emplace_back(t);               //如果最后仍然有进位
    return C;
}

int main(){
    string a,b;
    vector<int> A,B;
    cin >> a >> b;
    for(int i = a.size() - 1; i >= 0; i--) A.emplace_back(a[i] - '0');
    for(int i = b.size() - 1; i >= 0; i--) B.emplace_back(b[i] - '0');
    vector<int> C = add(A, B);
    for(int i = C.size() - 1; i >= 0; i--) cout << C[i];
    return 0;
}

减法

减法跟加法一样,需要额外考虑的是A与B谁大,并调用对应的减法函数并加上负号即可

#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;

//判断A是否大于B
bool cmp(vector<int>& A, vector<int>& B){
    if(A.size() != B.size()) return A.size() > B.size();    //位数不等
    for(int i = A.size() - 1; i >= 0; i--){                 //注意从大到小判断
        if(A[i] != B[i]) return A[i] > B[i];                //位数相等
    }
    return true;       //两者相等
}

//此时的算法是在确定A>B的基础上进行编写的
vector<int> sub(vector<int>& A, vector<int>& B){
    vector<int> C;
    int t = 0;           //应该压入数组的每一位数值
    for(int i = 0; i < A.size() || i < B.size(); i++){
        if(i < A.size()) t = A[i] - t;              //计算每一位需要A[i]-B[i]-t
        if(i < B.size()) t -= B[i];      
        C.emplace_back((t + 10) % 10); //如果求出来的值大于0,就是自身,如果小于零,就要借位+10,而这两种情况都可以用+10再模10进行一步运算
        if(t < 0) t = 1;       //如果t小于零,就说明借位了,需要赋值1,用于下一位的计算
        else t = 0;
    }
    while(C.size() > 1 && C.back() == 0) C.pop_back();   //去除前导零,例如11-11=00,需要把前面的0去掉同时保证如果答案就是0的时候则不去
    return C;
}

int main(){
    string a,b;
    vector<int> A,B;
    cin >> a >> b;
    for(int i = a.size() - 1; i >= 0; i--) A.emplace_back(a[i] - '0');
    for(int i = b.size() - 1; i >= 0; i--) B.emplace_back(b[i] - '0');
    if(cmp(A, B)){
        vector<int> C = sub(A, B);       //如果A>B,就用A-B
        for(int i = C.size() - 1; i >= 0; i--) cout << C[i];
    }
    else{
        vector<int> C = sub(B, A);       //如果A<B,就用B-A,然后加-号即可
        cout << "-";
        for(int i = C.size() - 1; i >= 0; i--) cout << C[i];
    }
    return 0;
}

乘法

跟加法差不多,不难,需要注意的是对 t t t 的额外处理

#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;

vector<int> mul(vector<int>& A, int b){
    vector<int> C;
    int t = 0;      //应该压入数组的每一位数值
    for(int i = 0; i < A.size() || t; i++){   //确保把T处理完
        if(i < A.size()) t += A[i] * b;   
        C.emplace_back(t % 10);
        t = t / 10;       //t不像加法,可能一次除不到位
    }
    return C;
}

int main(){
    string a;
    vector<int> A;
    int b;
    cin >> a >> b;
    for(int i = a.size() - 1; i >= 0; i--) A.emplace_back(a[i] - '0');
    vector<int> C = mul(A, b);
    for(int i = C.size() - 1; i >= 0; i--) cout << C[i];
    return 0;
}

除法

除法要求商和余数,且商和其他三个运算不同,因为除法是从最高位开始计算的,所以要搞清对于每一位应该是从小到大进行操作还是从大到小

#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;

vector<int> div(vector<int>& A, int b, int& t){
    vector<int> C;
    t = 0;                                    //应该压入数组的每一位数值
    for(int i = A.size() - 1; i >= 0; i--){   //和加减乘不同,除法要从最高位开始
        t = t * 10 + A[i];                    //算出每一步的被除数:当前位的数值*10+下一位
        C.emplace_back(t / b);                //入数组的是被除数除以除数
        t = t % b;                            //可能有余数,用于下一步的计算
    }
    reverse(C.begin(), C.end()); //由于最后是反着输出的,所以逆序一下
    while(C.size() > 1 && C.back() == 0) C.pop_back();  //跟减法一样,去除前导0
    return C;
}

int main(){
    string a;
    vector<int> A;
    int b;
    cin >> a >> b;
    for(int i = a.size() - 1; i >= 0; i--) A.emplace_back(a[i] - '0');
    int t;
    vector<int> C = div(A, b, t);
    for(int i = C.size() - 1; i >= 0; i--) cout << C[i];
    cout << " " << t;
    return 0;
}

前缀和

一维

#include<iostream>
using namespace std;

const int N = 100010;
int Array[N],s[N];

int main(){
    int n,m;
    cin >> n >> m;
    for(int i = 1; i <= n; i++){
        cin >> Array[i];
        s[i] = s[i-1] + Array[i];       //计算从下标1开始的前缀和
    }
    while (m--)
    {
        int low, high;
        cin >> low >> high;
        cout << s[high] - s[low-1] << endl;    //计算任意下标范围内的元素之和
    }
    return 0;
}

二维

在这里插入图片描述

画个图就能理解

#include<iostream>
using namespace std;

const int N = 1010;
int Array[N][N],s[N][N];

int main(){
    int n,m,q;
    cin >> n >> m >> q;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            cin >> Array[i][j];
            s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + Array[i][j];    //计算前缀和
        }
    }
    while (m--)
    {
        int x1,y1,x2,y2;
        cin >> x1 >> y1 >> x2 >> y2;
        cout << s[x2][y2] - s[x2][y1-1] - s[x1-1][y2] + s[x1-1][y1-1] << endl;   //求范围和
    }
    return 0;
}

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

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

相关文章

Docker的容器管理操作

Docker的容器管理操作Docker的容器管理操作1. 创建容器2. 启动容器3、查看容器的运行状态4、创建并启动容器5、在后台持续运行 docker run 创建的容器6、停止容器7、 删除容器8、 容器的进入9、查看容器的元数据——docker inspect10、容器日志11、宿主机和容器之间的文件复制将…

Android——FloatingActionButton使用说明以及避坑

1、简介 1.1、 com.android.support库下 compile com.android.support:design:26.0.0 1.2、material库下 com.google.android.material.floatingactionbutton.FloatingActionButton 库下 implementation com.google.android.material:material:1.1.0 官方地址&#xff1a;…

怎么有效地进行问卷发放?

进行问卷调查分为四步&#xff1a;制作问卷、发放问卷、收集问卷、分析问卷。其中&#xff0c;发放问卷起到了关键性的作用。他关乎到我们后续收集问卷是否顺利&#xff0c;收集到的问卷数据是否具备真实性和有效性。那么&#xff0c;怎么有效地进行问卷发放呢&#xff1f; 1、…

右键实现打开对应的软件

右键实现打开对应的软件前言&#xff1a;下面我以右键打开Pycharm为例子&#xff01;&#xff01;&#xff01;一、打开注册表1.1 WinR&#xff0c;输入regedit,回车二、实现右键打开特定文件的效果2.1找到路径&#xff1a;计算机\HKEY_CLASSES_ROOT\*\shell2.2 创建文件夹2.3 …

【In-Context Learning】Meta-learning via Language Model In-context Tuning

In-Context Learning是最近比较火热的方向&#xff0c;其主要针对超大规模模型&#xff08;例如1750B参数量的GPT-3模型&#xff09;&#xff0c;在只提供少量标注样本作为提示的前提下&#xff0c;即可以实现很惊艳的效果。本文将元学习引入到In-Context Learning中。 论文PDF…

企业实践开源的动机

文章来源&#xff1a;” 夜天之书 “微信公众号 作者&#xff1a;tison 随着开源软件全面占据软件供应链的各个阶段&#xff0c;商业公司开发基础软件或业务逻辑的时候&#xff0c;已经避不开对软件的使用了。经过一段时间对开源软件的使用&#xff0c;以及开源吞噬软件的趋势…

海量Redis数据库优化,vivo如何实现成本与性能的平衡

概述 随着数字化技术的创新以及时延敏感型应用的持续落地&#xff0c;越来越多的数据需要实现实时或近实时的处理&#xff0c;这推动了 Redis 等内存数据库的广泛应用。此类数据库对于内存容量有着较高的要求&#xff0c;在数据快速增长的背景下&#xff0c;大内存池构建意味着…

分布式监控平台——Zabbix

市场上常用的监控软件&#xff1a; 传统运维&#xff1a;zabbix、 Nagios云原生环境&#xff1a; Prometheus &#xff08;go语言开发的&#xff09; 一 Zabbix概述 作为一个运维&#xff0c;需要会使用监控系统查看服务器状态以及网站流量指标&#xff0c;利用监控系统的数据…

二叉树的遍历-树-数据结构和算法(Java)

1 树的遍历方式 1.1 深度优先 事实上&#xff0c;深度优先搜索属于图算法的一种&#xff0c;英文缩写为DFS即Depth First Search.其过程简要来说是对每一个可能的分支路径深入到不能再深入为止&#xff0c;而且每个节点只能访问一次. 那么对于树来说&#xff0c;"深度优先…

使用阿里云国际版负载均衡管理多台服务器上的流量

有效处理多云服务器设置的流量和数据传输负载可能是一个复杂的过程。然而&#xff0c;这是完全必要的&#xff0c;因为业务关键型应用程序需要高度可用的解决方案来管理繁重的工作负载。阿里云服务器负载均衡器(SLB) 简化了工作负载在服务器、网络链路和其他资源之间的分配&…

[附源码]SSM计算机毕业设计闲置物品交易管理系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

mac系统废纸篓可以恢复么,mac不小心清空了废纸篓怎么找回

在使用Mac电脑的过程中&#xff0c;有可能会出现各种意外&#xff0c;其中误删文件是很常见的一种。如果你不小心删除了废纸篓里还有用的文件&#xff0c;mac系统废纸篓可以恢复么&#xff1f; 一、我不小心删除了重要文件&#xff0c;还清倒了废纸篓 案例分享&#xff1a;mac…

软件测试面试题-一个前后端都能修改的bug,应该由谁修改?

其实这个问题还是问得比较有水平的一道面试题。 有很多人说&#xff0c;要不前端修改吧。那难道后端就不能修改吗&#xff1f; 之后又有人说&#xff0c;要不后端修改吧&#xff0c;那难道前端就不能修改吗&#xff1f; 瞬间求职者一脸懵逼。。。。 这道题该怎么去回答呢&…

在国内CDMP认证认可度如何?

随着数字化转型的深入&#xff0c;中国企业不再唯技术论&#xff0c;开始进行转型的整体思考和创新突破。数据是构成数字化业务重要材料&#xff0c;是企业运营变革和竞争优势塑造的核心动力&#xff0c;是实现数字化转型的坚实基础。越来越多的国内企业认识到数据治理知识在企…

spring复习04,静态代理动态代理,AOP

spring复习04,静态代理动态代理,AOP概念引入java代理模式静态代理静态代理模式的好处:静态代理模式的缺点&#xff1a;动态代理jdk动态代理1. InvocationHandler接口2. Proxy类jdk动态代理代码AOPAOP的概念spirng中aop的实现方式一&#xff1a;spring原生的接口方式二&#xff…

基于树莓派的freeRDP桌面云终端的简单实现

VDI虚拟桌面云系统可以通过RmoteFX, PCoIP,HDX等远程桌面显示协议将服务器端的虚拟操作系统桌面环境在远程云终端上显示出来。商用的VDI系统需要部署服务器端虚拟机管理软件如System Center, XenServer等软件,购买价格不菲的服务器硬件,以及500~1000元之间的云终端接入设备。…

模糊控制算法实例matlab程序

参考文献《智能控制——刘金锟》 以水位的模糊控制为例。如图4一4所示&#xff0c;设有一个水箱&#xff0c;通过调节阀可向内注水和向外抽水。设计一个模糊控制器&#xff0c;通过调节阀门将水位稳定在固定点附近。按照日常的操作经验&#xff0c;可以得到基本的控制规则为&am…

TikTok营销策略 如何打造TikTok爆款视频?

最近&#xff0c;电商商家们总在问&#xff0c;如何打造出TikTok爆款视频&#xff0c;以吸引更多浏览量&#xff0c;刺激TikTok变现。这里不难发现&#xff0c;视频创作也只是一种TikTok营销方式&#xff0c;今天就来说说如何打造TikTok爆款视频。TikTok视频营销策略一——清晰…

模型案例推荐:电力大数据项目案例模型分享

电力行业大数据项目模型 电力高架线路巡检绝缘子缺陷智能检测 涉及关键技术&#xff1a; 语义分割 目标检测 图像增强 图像切分 主要工具&#xff1a;Python 技术大类&#xff1a;计算机视觉 主要业务问题&#xff1a; 随着我国经济的高速发展&#xff0c;国民用电量逐年增…

SpringCloud - Sleuth分布式请求链路跟踪

文章目录一.概述二.zipkin搭建三.Sleuth链路监控实现1. payment8001生产者修改2. Consumer80消费者修改3. 测试一.概述 在微服务框架中&#xff0c;一个由客户端发起的请求在后端系统中会经过多个不同的的服务节点调用来协同产生最后的请求结果&#xff0c;每一个前段请求都会…