算法基础第一章

news2025/1/20 13:17:35

算法基础

  • 第一章:基础算法
    • 1、排序
    • 2、二分查找
    • 3、大数据量的加法和减法(高精度加减法)
      • 3.1、加法
      • 3.2、减法
    • 4、前缀和
      • 4.1、一维前缀和
      • 4.2、二维前缀和
    • 5、差分
      • 5.1、一维差分
      • 5.2、二维差分
    • 6、双指针
    • 7、位运算
      • 7.1、lowbit的应用
    • 8、离散化
    • 9、区间合并
  • 第二章:数据结构
  • 第三章:搜索与图论
  • 第四章:数学知识
  • 第五章:动态规划
  • 第六章:贪心算法

第一章:基础算法

1、排序

  • 各种排序算法

2、二分查找

  • 描述:在一个有序数组里面查找某个目标值
  • 解析:
    • mid = left + (right - left)/2;
      • mid所在的val小于target_val的时候,left = mid + 1,即区间取右半区间
      • mid所在的val小于target_val的时候,right = mid - 1,即区间取左半区间
        在这里插入图片描述
  • 牛客题目链接:二分查找
  • 代码
class BinarySearch {
public:
    int getPos(vector<int> A, int n, int val) {
        // write code here
        int left = 0,right = n-1;
        while(left <= right)
        {
            int mid = left + (right - left)/2;
            if(A[mid] == val)
            {
                auto i = mid - 1;
                for(;i>=0 && A[i] == val;i--)
                {
                }
                return i+1;
            }
            else if(A[mid] > val)
            {
                right = mid - 1;
            }
            else {
                left = mid + 1;
            }
        }
        return -1;
    }
};

3、大数据量的加法和减法(高精度加减法)

3.1、加法

  • 描述:超出数据类型范围的数的相加

  • 解析:

    • 存储:为了方便进位,则把低位数保存在容器的低位
    • 运算:对应位的和为(C+Ai+Bi)%10,进位为C/10;
    • 全部算完之后还要判断最高位是否有进位,有的话把进位再插入容器
    • 输出的时候逆序输出
      在这里插入图片描述
  • 牛客题目链接:高精度加法

  • 代码

#include <iostream>
#include<string>
#include<vector>

using namespace std;

const int N = 10000;

void 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];
        C.push_back(t%10);
        t /= 10;
    }
    if(t > 0)
        C.push_back(t);
}
int main() {
    string a,b;
    cin >> a >> b;
    vector<int>A,B,C;
    for(int i = a.length()-1; i >= 0; i--)
    {
        A.push_back(a[i] - '0');
    }
    for(int i = b.length()-1; i >= 0; i--)
    {
        B.push_back(b[i] - '0');
    }
    add(A,B,C);
    for(int i = C.size()-1; i >= 0; i--)
    {
        printf("%d",C[i]);
    }
}
// 64 位输出请用 printf("%lld")

3.2、减法

  • 描述:超出数据类型范围的数的减法

  • 解析:A>B则用A-B;A<B则用-(B-A),相减的时候为对应位相减且减去借位c,c起始为0,得到的结果分为大于0和小于0,大于0则直接得到输出结果,小于0则还需要加上10,两个可合并为(sum+10)%10,最后还要判断下一位的借位
    在这里插入图片描述

  • 题目链接:未找到

#include<iostream>
#include<vector>
#include<string>

using namespace std;
/* 比较两个数的大小,从高位往低位依次比较 */
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;
}

vector<int>sub(vector<int>&A,vector<int>&B)
{
    vector<int>C;
    for(int i = 0,c=0; i < A.size(); i++)
    {
    	/* c是借位 */
        c = A[i] - c;
        if(i < B.size())
            c -= B[i];
        C.push_back((c+10)%10);
        if(c < 0)
            c = 1;
        else
            c = 0;
    }
    /* 去掉前导0,全为0则保留最后一个0 */
    while(C.size() > 1 && C.back() == 0)
        C.pop_back();
    return C;
}


int main()
{
    string a,b;
    vector<int>A,B;
    cin >> a >> b;
    /* 低位数存入容器的低位位置 */
    for(int i = a.length()-1; i >= 0; i--)
    {
        A.push_back(a[i] - '0');
    }
    for(int i = b.length()-1; i >= 0; i--)
    {
        B.push_back(b[i] - '0');
    }
    
    if(cmp(A,B))
    {
        auto C = sub(A,B);

        for(int i = C.size()-1; i >= 0; i--)
        {
            printf("%d",C[i]);
        }
    }
    else
    {
        auto C = sub(B,A);
        printf("-");
        for(int i = C.size()-1; i >= 0; i--)
        {
            printf("%d",C[i]);
        }
    }
}

4、前缀和

4.1、一维前缀和

  • 描述:在一个一维数组里面求某一段区间内的和
  • 解析:
    • 数组a[N],S[i] = S[i-1]+a[i],区间l到r的和为S[r]-S[l-1]
  • 题目链接:前缀和
  • 代码
#include <iostream>
#include<vector>
#include<bits/stdc++.h>

using namespace std;

const int N = 100010;
int a[N];
long long S[N];

int main() {
    int n,q;
    cin >> n >> q;

    for(int i = 1; i <= n; i++)
    {
       scanf("%d",&a[i]);
       S[i] = S[i-1] + a[i];
    }
    while(q--)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        printf("%lld\n",S[r] - S[l-1]);
    }
    return 0;
}
// 64 位输出请用 printf("%lld")

4.2、二维前缀和

  • 描述:一个二维矩阵A[n][m],求其(x1,y1)和其(x2,y2)之间的矩阵和
  • 解析:先算出S[i][j],再算两点间的和
  • 求S[i][j]的和
  • 计算两点间的和,注意边界,需要包含x1,y1
    在这里插入图片描述
  • 题目链接:二维前缀和
  • 代码
#include <iostream>
#include<bits/stdc++.h>
using namespace std;

const int N = 1010;
int A[N][N];
long long 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 >> A[i][j];
            S[i][j] = S[i][j-1] + S[i-1][j] - S[i-1][j-1] + A[i][j];
        }
    }

    while(q--)
    {
        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;
    }
}

5、差分

5.1、一维差分

  • 描述:在a[n]这个数组中的某一段全部加上某个数
  • 解析:an是bn的前缀和,bn是an的差分,在bl+k,在b(r+1)-k,相当于只在l到r这段里面的数加上了k
    在这里插入图片描述
  • 题目链接:一维差分
  • 代码
#include <iostream>
using namespace std;

const int N = 100010;
int n,m;
long long a[N],b[N];

void insert(int l,int r,int k)
{
    b[l] += k;
    b[r + 1] -= k;
}
int main() {
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
    {
        cin >> a[i];
        insert(i, i, a[i]);
    }
       
    while(m--)
    {
        int l,r,k;
        cin >> l >> r >> k;
        insert(l, r, k);
    }
    for(int i = 1; i <= n; i++)
    {
        b[i] += b[i-1];
        cout << b[i] << " ";
    }
}

5.2、二维差分

  • 描述:将二维矩阵中的其中一个子矩阵每个数都加上一个数
  • 解析:只将图中的子矩阵中的每个数加上c,表达式如图中所示
    在这里插入图片描述
  • 同样b[i][j]是a[i][j]的差分,a是b的前缀和,也就是b[i][i]上方的子矩阵的和就为a[i][j],前缀和公式如图
    在这里插入图片描述
  • 题目链接:二维差分
  • 代码
#include <iostream>
using namespace std;

const int N = 1010;
long long a[N][N],b[N][N];
int n,m,q;

void insert(int x1,int y1,int x2,int y2,int c)
{
    b[x1][y1] += c;
    b[x2+1][y1] -= c;
    b[x1][y2+1] -= c;
    b[x2+1][y2+1] += c;
}
int main() {
    cin >> n >> m >> q;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
        {
            cin >> a[i][j];
            insert(i,j,i,j,a[i][j]);
        }
    while(q--)
    {
        int x1,y1,x2,y2,k;
        cin >> x1 >> y1 >> x2 >> y2 >> k;
        insert(x1,y1,x2,y2,k);
    }
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            b[i][j] += b[i-1][j] + b[i][j-1] - b[i-1][j-1];
            cout << b[i][j] << " ";
        }
        cout << endl;
    }
}

6、双指针

  • 题目链接:最长连续无重复子序列
  • 代码
#include <unordered_map>
class Solution {
public:
    int maxLength(vector<int>& arr) {
        int n = arr.size();
        unordered_map<int, int>mp;
        int ret = 0;
        for(int i = 0,j = 0; i < n; i++)
        {
            mp[arr[i]]++;
            while(mp[arr[i]] > 1)
            {
                mp[arr[j]]--;
                j++;
            }
            ret = max(ret,i-j+1);
        }
        return ret;
    }
};

7、位运算

7.1、lowbit的应用

  • 描述:求x的第k位的大小
  • 公式:(x >> k) & (-x)
    在这里插入图片描述
  • 题目链接:二进制数中1的个数

8、离散化

  • 描述:在一个无限长的坐标中进行添加和询问操作,坐标上的数起始全为0,add的(1,2)表示在坐标1加2,query的(1,2)表示求区间1,2之间的和,和为5,所以输出5
    在这里插入图片描述

  • 解析:1、将操作的下标全部存进容器,排序后去重;2、使用二分查找算出离散化的值;3、再使用前缀和算出结果

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

using namespace std;

typedef pair<int,int>PII;

const int N = 300010;

int n,m;
int a[N],S[N];

vector<int>alls;
vector<PII>add,query;

int find(int x)
{
    int l=0,r=alls.size()-1;
    while(l<r)
    {
        int mid = l+r >> 1;
        if(alls[mid] >= x)
            r = mid;
        else
            l = mid + 1;
    }
    return r + 1;
}

int main()
{
    cin >> n >> m;
    for(int i = 0; i < n; i++)
    {
        int x,c;
        cin >> x >> c;
        add.push_back({x,c});
        alls.push_back(x);
    }
    for(int i = 0; i < m; i++)
    {
        int l,r;
        cin >> l >> r;
        query.push_back({l,r});
        alls.push_back(l);
        alls.push_back(r);
    }
    sort(alls.begin(),alls.end());
    alls.erase(unique(alls.begin(),alls.end()),alls.end());
    for(auto item:add)
    {
        int x = find(item.first);
        a[x] += item.second;
    }
    for(int i=1;i<=alls.size();i++)
        S[i] = S[i-1] + a[i];
    for(auto item:query)
    {
        int l = find(item.first),r = find(item.second);
        cout << S[r] - S[l-1] << endl;
    }
    return 0;
}

9、区间合并

  • 描述:给定多个区间,将能合并的合并,不能合并的保留,最后输出所有区间
  • 解析:先将所有的区间排序,比较维护区间的右区间端点和新区间的左端点,如果新区间的左端点比维护区间的右端点大,则两个不能合并,将维护的区间保存起来,新区间变成维护区间接着往下比较,一直到最后一个
  • 题目链接:区间合并
#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

typedef pair<int,int>PII;

vector<PII>store;
vector<PII>ret;

void merge(vector<PII>&tmp)
{
    int st = -2e9,ed = -2e9;
    sort(tmp.begin(),tmp.end());
    for(auto c:tmp)
    {
        if(ed < c.first)
        {
            if(st != -2e9) ret.push_back({st,ed});
            st = c.first,ed = c.second;
        }
        else
            ed = max(ed,c.second);
    }
    if(st != -2e9) ret.push_back({st,ed});
}
int main()
{
    int n,st,ed;
    cin >> n >> st >> ed;
    for(int i = 0; i < n; i++)
    {
        int l,r;
        cin >> l >> r;
        store.push_back({l,r});
    }
    store.push_back({st,ed});
    merge(store);
    /* 输出 */
    for(auto c:ret)
    {
        cout << c.first << c.second << endl;
    }
}

第二章:数据结构

第三章:搜索与图论

第四章:数学知识

第五章:动态规划

第六章:贪心算法

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

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

相关文章

基于c与数据库实现的电子词典

1.搭建客户端与服务器&#xff0c;客户端使用多线程方式&#xff0c;主线程跑发送信息给服务器功能&#xff0c;分支线程跑循环接收服务器信息功能 客户端代码&#xff1a; //TCP客户端的搭建 int tcp_kehuduan() {//创建字节流套接字cfd socket(AF_INET,SOCK_STREAM,0);if(c…

【TCP服务器的演变过程】C++使用libevent库开发服务器程序

C使用libevent库开发服务器程序 一、引言二、libevent简介三、Libevent库的封装层级3.1、reactor对象封装struct event_base3.2、事件对象struct event3.3、struct bufferevent对象3.4、evconnlistener对象3.5、事件循环3.6、事件处理 四、完整示例代码小结 一、引言 手把手教…

病毒的遗传分析

噬菌体的生活周期 烈性噬菌体 噬菌体吸附到宿主细胞上尾丝鞘收缩,中轴刺穿宿主细胞头部的DNA被送入宿主细胞在数分钟内,所有的细菌核算和蛋白质合成都被抑制 噬菌体大分子合成(DNA,蛋白外壳),细菌的核算被降解 噬菌体组装:DNA被包到头部,组装尾部,装上尾丝 宿主细胞破裂:约20…

新品首发丨计讯物联5G水利遥测终端机TY511-B3,推动5G+智慧水利再进化

当前&#xff0c;水利在全面感知、全面互联、智慧应用等方面较其他行业存在明显差距。基于物联网行业通信技术的不断突破和水利行业对高速移动通信的强烈需求&#xff0c;5G移动通信以高速率、大带宽、低时延、广连接等特点让水利数据快速高效地传输成为可能&#xff0c;逐渐成…

如何优雅的写个try catch的方式!

软件开发过程中&#xff0c;不可避免的是需要处理各种异常&#xff0c;就我自己来说&#xff0c;至少有一半以上的时间都是在处理各种异常情况&#xff0c;所以代码中就会出现大量的try {...} catch {...} finally {...} 代码块&#xff0c;不仅有大量的冗余代码&#xff0c;而…

流程图拖拽视觉编程-流程编辑器2

目录 一、简介 二、自定义图元 2.1图元设计 2.2 端口QNEPort 2.3节点块QNEBlock 一、简介 前期文章&#xff1a; 流程图拖拽视觉编程--概述_Jason~shen的博客-CSDN博客 流程图拖拽视觉编程-流程编辑器_Jason~shen的博客-CSDN博客 本期内容&#xff1a; 本期将继续介绍…

【Leetcode】236.二叉树的最近公共祖先

二叉树的最近公共祖先 题目思路1思路2代码 题目 思路1 给我们两个二叉树中的节点 找出里面的最近公共祖先 首先我们要分析p q 两点有哪些位置关系 p q在根节点的两侧 此时最近公共祖先就是根节点 在根节点一侧 此时两个节点都在根节点左侧 此时可以递归二叉树 让root.left…

内存取证小练习-基础训练

这是题目和wolatility2.6的链接 链接&#xff1a;https://pan.baidu.com/s/1wNYJOjLoXMKqbGgpKOE2tg?pwdybww 提取码&#xff1a;ybww --来自百度网盘超级会员V4的分享 压缩包很小&#xff0c;题目也比较简单基础&#xff0c;可以供入门使用 1&#xff1a;Which volatility…

使用auto-gpt来写一篇技术文章(如何部署autogpt+遇到的问题+如何使用)

文章目录 前言一、autogpt本地部署1.clone代码2.启动虚拟环境3.运行项目 二、使用aotogpt生成文章1.人设描述2.设置目标3.文章的生成过程4.文章的生成内容 总结 前言 最近AI技术的发展非常迅猛&#xff0c;尤其是和GPT相关的技术&#xff0c;备受瞩目。近日&#xff0c;Autogp…

nvm安装管理npm

1.根据http://t.csdn.cn/mRwCQ这个教程完成安装 2.使用nvm install [指定版本号]&#xff0c;下载了16.15.1&#xff0c;和10.15.1版本 2.5 这里其实出了一点问题&#xff0c;我在下载16.15.1时&#xff0c;因为墙的问题其实是下载出错&#xff0c;报了一个error的&#xff0c…

手推A Unified Solution to Constrained Bidding in Online Display Advertising论文

A Unified Solution to Constrained Bidding in Online Display Advertising&#xff1a;一种对在线展示广告约束出价问题的通用解决方案 未开放但是可以搜到 NeuralAuction: 电商广告中的端到端机制优化方法 https://arxiv.org/abs/2106.03593 一种使用真负样本的在线延迟反…

JVM,关于JVM基础的知识,你确定不了解一下吗?

目录 一.JVM的概念 什么是JVM&#xff1f; 二.JVM的运行流程 1.class文件如何被JVM加载并运行 2.JVM运行时数据包括哪些区域&#xff08;M&#xff09; 三.类加载的过程&#xff08;M&#xff09; 四.双亲委派模型 1.双亲委派模型分析 2.JAVA中有哪些类加载器&#xf…

Maven私服搭建

为什么要搭建私服 通常在maven项目的pom.xml文件中引入了某个依赖包之后&#xff0c;maven首先会去本地仓库去搜索&#xff0c;本地仓库搜索不到会去maven的配置文件settings.xml中配置的maven镜像地址去找&#xff0c;比如&#xff1a; <mirrors><!-- mirror| Specif…

动态规划 --- 电线布设

动态规划 — 电线布设 题目描述 说是话&#xff0c;刚看到也是很懵逼&#xff0c;不想交子集是什么&#xff1f;乱七八糟的连线。 其实仔细想想后&#xff0c;觉得题目应该是说给定了这些点的连接端点&#xff0c;然后从他给的连线中选择出不想交的且条数最多的连线&#x…

Flink自定义函数之标量函数(UDF函数)

1.背景 flink本身给我们提供了大量的内置函数&#xff0c;已经能满足我们绝大部分的需求&#xff0c;但是如果确实是碰到了一些特殊的场景&#xff0c;无法满足我们的需求的时候&#xff0c;我们可以使用自定义函数来解决。 自定义函数大致可以分为标量函数&#xff08;UDF函…

Linux-安装Python2.7

一、简介 正常情况下&#xff0c;使用sudo apt install python来安装就好了。如果发现这个指令报错了&#xff0c;此时就需要手动安装Python2.7了。例如报错如下&#xff1a; 二、实操 1.下载Python2.7的相关源码&#xff08;以2.7.18为例&#xff09; 下载地址如下&#xff1a…

Linux第四章

文章目录 前言一、快捷键小技巧二、软件安装三、systemctl控制软件启动关闭四、软链接五、日期和时区六、ip地址和主机名七、配置linux固定ip地址八、网络请求和下载九、端口十、进程管理十一、主机状态监控十二、环境变量十三、linux文件的上传和下载十四、压缩和解压总结 前言…

第五章 使用RAID与LVM磁盘阵列技术

第五章 使用RAID与LVM磁盘阵列技术 一、RAID磁盘冗余阵列 1、部署磁盘阵列 &#xff08;1&#xff09;、RAID0、1、5、10方案技术对比 RAID级别最少硬盘可用容量读写性能安全性特点02nn低追求最大容量和速度&#xff0c;任何一块盘损坏&#xff0c;数据全部异常。12n/2n高追…

魔兽世界服务端用户注册以及网页的搭建教程

魔兽世界服务端用户注册以及网页的搭建教程 大家好我是艾西&#xff0c;上一章我们讲解了怎么编译一个魔兽的服务端以及安装最后进到我们自己的游戏。那么在平时娱乐的同时肯定是需要和朋友们一起玩游戏才会更有意思&#xff0c;那么今天艾西教大家怎么搭建用户注册页面以及网…

java进程引发的内存泄露问题排查分析

近期工作过程中遇到了一次容器内存不断增高&#xff0c;最终达到90%引发告警的情况。 特征1&#xff0c;把监控面板时间轴拉长会发现&#xff0c;重启后内存占用78%左右&#xff0c;每天增长1%&#xff0c;大约2周后会涨到90%触发告警&#xff08;即如果2周内有代码发布部署&am…