基础算法(二)

一 高精度计算

  int能表示范围为2^32,这看起来很大,但在大数据时代的如今,不说是int 哪怕是long long也是不够的,那么为了使用或计算这些超出或远超整形大小的数,我们这些数的计算方法称为高精度计算。

(1)高精度加法(A+B,A和B均为高精度)

  我们采用的方法是开两个数组A,B,然后用这两个数组来模拟两个大数之间的加法运算。代码实现要注意两个细节:
  ①实现过程中一定要保证A的长度大于B
  ②实现过程中注意数的存储顺序是从低位向高位,具体过程如下所示:
在这里插入图片描述
  代码如下所示:

vector<int> add(vector<int> &A, vector<int> &B)
{if (A.size() < B.size()) return add(B, A);vector<int> C;int t = 0;//t用于表示进位for (int i = 0; i < A.size(); i ++ ){t += A[i];if (i < B.size()) t += B[i];C.push_back(t % 10);t /= 10;}if (t!=0) C.push_back(t);//用于保存进位return C;
}

(2)高精度减法(满足A>B)

  思路和高精度加法基本一致,只是模拟的过程是减法而不是加法

vector<int> sub(vector<int> &A, vector<int> &B)
{vector<int> C;for (int i = 0, t = 0; i < A.size(); i ++ ){t = A[i] - t;if (i < B.size()) t -= B[i];C.push_back((t + 10) % 10);if (t < 0) t = 1;else t = 0;}while (C.size() > 1 && C.back() == 0) C.pop_back();//去掉首位的所有0return C;
}

二 前缀和与差分

  这两种方法都是预处理方式,可以降低达到某种操作时间复杂度
  前缀和降低时间复杂度的代表操作为求某一个区间的和
  差分时间复杂度的代表操作为给区间内每一个数加上一个固定常数

(1)前缀和

  前缀和是一种重要的预处理,能大大降低查询的时间复杂度通常用于处理获取某一部分连续区间的问题。前缀和是以求和的方式灵活地面对区间询问。例如以下问题:
  给你一串长度为 n 的数列 a1, a2, a3, …, an,再给出 m 个询问,每次询问给出 L, R 两个数,要求给出区间 [L, R] 里的数的和。如果使用前缀和处理以后很容易可以得到
则上述题目的结果为 S [ L ] − S [ R − 1 ] 则上述题目的结果为S[L]-S[R-1] 则上述题目的结果为S[L]S[R1]
  时间复杂度显然降低

  ①一维前缀和(用于处理一维数组)

表达式为 S [ n ] = a 1 + a 2 + a 3 + . . . . a n 预处理递推公式为: S [ n ] = S [ n − 1 ] + a n 表达式为S[n]=a_1+a_2+a_3+....a_n\\预处理递推公式为:S[n]=S[n-1]+a_n 表达式为S[n]=a1+a2+a3+....an预处理递推公式为:S[n]=S[n1]+an
  ②二维前缀和(用于处理二维数组)
  二维前缀和的公式如下
二维前缀和表达式为: S [ x , y ] = ∑ i = 1 x ∑ i = 0 y a i j 预处理递推公式为: S [ x , y ] = S [ x − 1 , y ] + S [ x , y − 1 ] − S [ x − 1 , y − 1 ] + a x y 二维前缀和表达式为:S[x,y]=\sum_{i=1}^x\sum_{i=0}^ya_{ij}\\预处理递推公式为:\\S[x,y]=S[x-1,y]+S[x,y-1]-S[x-1,y-1]+a_{xy} 二维前缀和表达式为:S[x,y]=i=1xi=0yaij预处理递推公式为:S[x,y]=S[x1,y]+S[x,y1]S[x1,y1]+axy
  这个公式可以根据以下方法记忆:


  代码实现思路如下:
  (1)初始化所有的S[n][0],S[0][m](第一行与第一列)
  (2)根据递推公式推出所有的S[x][y]

(2)差分思想(也存在二维差分)

  差分:一个数列,如果知道第一个数,以及每一个数与前一个数的差值,那么我们就可以推出整个数列。前缀和与差分运算为互逆运算。差分数组d[n]的公式如下:
d [ i ] = { a [ i ] , i = 1 a [ i ] − a [ i − 1 ] , i > 1 d[i]=\left\{ \begin{aligned} a[i],i=1 \\ a[i]-a[i-1],i>1 \end{aligned} \right. d[i]={a[i],i=1a[i]a[i1],i>1
  所以可以推出公式:
a [ n ] = ∑ i = 1 n d [ i ] a[n]=\sum_{i=1}^nd[i] a[n]=i=1nd[i]
  下面介绍一个差分算法很重要的应用:给定区间[l ,r ],让我们把a数组中的[ l, r]区间中的每一个数都加上c,即 a[l] + c , a[l+1] + c , a[l+2] + c , a[r] + c;
  暴力做法是for循环l到r区间,时间复杂度O(n),这个时候使用差分数组时间效率就大大提高了。根据差分的公式,可知道:
b [ n ] + = c , a [ i ] 全部都加 c b [ n ] − = c , a [ i ] 全部减去 c 以上两个式子都是在 i > = n 的时候成立 b[n]+=c,a[i]全部都加c\\b[n]-=c,a[i]全部减去c\\以上两个式子都是在i>=n的时候成立 b[n]+=c,a[i]全部都加cb[n]=c,a[i]全部减去c以上两个式子都是在i>=n的时候成立
  所以具体方法是:这样就不用暴力循环每个数都加上c,只需要构造根据数组a构造差分数组b,而后对差分数组b做 b[l] + = c, b[r+1] - = c。要哪个数就进行b[n]数组的求和就行,从效果上看也达到了暴力做法的效果,但是只改了两个地方。

三 双指针算法

  双指针只能说是是算法中的一种技巧。双指针指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行扫描,从而达到相应的目的。
  双指针算法的核心思想就是运用某个性质,使用两个指针把时间复杂度优化。代码模板如下:

for (int i = 0, j = 0; i < n; i ++ )
{while (j < i && check(i, j)) j ++ ;
}

四 离散化

  离散化,把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小。例如:
在这里插入图片描述
可以使用以下代码实现:思路就是使用二分查找找到对应下标。

vector<int> alls; // 存储所有待离散化的值
sort(alls.begin(), alls.end()); // 将所有值排序
alls.erase(unique(alls.begin(), alls.end()), alls.end());   // 去掉重复元素// 二分求出x对应的离散化的值
int find(int x) // 找到第一个大于等于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; // 映射到1, 2, ...n
}

五 位运算

  (1)判断正整数N的二进制表示的第k位数步骤:将N右移k-1位以后与1进行与运算,如下列公式所示:

                           N>>(k-1)&1

  (2)lowbit操作:返回N的最小的2的次方数
6 = ( 110 ) 2 = 2 2 + 2 1 , 则 6 的最后一位 1 就是( 10 )也就是 2 6=(110)_2=2^2+2^1,则6的最后一位1就是(10)也就是2 6=(110)2=22+21,6的最后一位1就是(10)也就是2
  代码如下

                                N&-N

  用这个代码可以判断N中1的个数,具体方法就是每执行一次lowbit操作得到N的最小的2的次方数,然后减去lowbit操作的返回值。而后再执行lowbit操作直到N等于0位置,N执行了多少次lowbit操作就有几个1
  原理如下:
我们知道计算机这种负数就是取反再加 1 , 设 N = ( 10110......10.....0 ) 2 , 则 − N = ( 01001......01.....1 ) 2 + 1 = ( 01001......10....0 ) 2 则上述代码的结果为 10.....0 , 就是 N 的最后一位 1 我们知道计算机这种负数就是取反再加1,\\设N=(10110......10.....0)_2,\\则-N=(01001......01.....1)_2+1=(01001......10....0)_2\\则上述代码的结果为10.....0,就是N的最后一位1 我们知道计算机这种负数就是取反再加1N=10110......10.....0)2,N=01001......01.....1)2+1=01001......10....0)2则上述代码的结果为10.....0,就是N的最后一位1

六 区间合并

  区间合并问题也是一个贪心问题,由于比较常用所以单独拿出来。区间合并的解决方法是:把所有区间按照左端点从小到大排序,如果遍历到区间和维护的区间有交集,就合并(能合则合),没有交集的时候,当前维护的区间就变成这个遍历到的区间

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

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

相关文章

代码随想录 Leetcode113. 路径总和 II

题目&#xff1a; 代码(首刷看解析 2024年1月30日&#xff09;&#xff1a; class Solution { public:vector<int> temp;vector<vector<int>> res;void recursion(TreeNode* cur, int sum) {if (!cur->left && !cur->right && sum 0…

Java进击框架:Spring-WebFlux(九)

Java进击框架&#xff1a;Spring-WebFlux&#xff08;九&#xff09; 前言Mono和FluxSpring WebFlux反应的核心DispatcherHandler带注释的控制器WebFlux配置 WebClient配置retrieve()交换请求正文Filters属性语境同步使用测试 RSocket反应库 前言 Spring框架中包含的原始web框…

Jmeter分布式场景

Jmeter分布式 1. 为什么使用Jmter分布式测试 1.1 需求 对学院接口(查询学院-所有)进行1000用户并发访问&#xff0c;测试服务器处理批量请求能力1.2 现状 我们单台电脑由于配置(CPU、内存)问题&#xff0c;最模拟500用户时&#xff0c;就出现卡死现象按照一般的压力机配置&…

1. 两数之和(力扣LeetCode)

文章目录 1. 两数之和题目描述哈希表&#xff1a;map二分查找暴力&#xff1a;双重for循环 1. 两数之和 题目描述 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可…

24. 两两交换链表中的节点(力扣LeetCode)

文章目录 24. 两两交换链表中的节点题目描述解题思路只使用一个临时节点使用两个临时节点 24. 两两交换链表中的节点 题目描述 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff0…

angular2 开发遇到的问题

1&#xff1a;插件使用&#xff0c;要一同引入 不然报错 “ \ Changes detected. Rebuilding...X [ERROR] NG8001: sf-dashboard-overview is not a known element:”

微信扫码登录流程

微信官方文档使用 搜索“微信开放平台”点击导航栏的“资源中心”点击“网站应用”下的“微信登录功能”地址微信扫码登录是基于OAuth2的&#xff0c;所以需要第三方应用&#xff08;就是实现微信扫码登录的应用&#xff09;成为微信的客户端&#xff0c;获取AppId和AppSecret…

Linux 进程管理

一、简述 当运行一个程序的时候&#xff0c;那么运行的这个程序就叫做进程。程序&#xff0c;是一个静态的概念统称为软件&#xff0c;相当于一个被编译好可执行的二进制文件&#xff0c;同时程序可以长期存在系统中&#xff1b;进程&#xff0c;是一个动态的概念&#xff0c;…

RHCE练习3

1.基于域名www.openlab.com可以访问网站内容为 welcome to openlab 2.给该公司创建三个子界面分别显示学生信息&#xff0c;教学资料和缴费网站&#xff0c;基于www.openlab.com/student 网站访问学生信息&#xff0c;www.openlab.com/data网站访问教学资料www.openlab.com/mo…

Unix环境高级编程-学习-04-匿名管道PIPE

目录 一、环境 二、介绍 三、C标准函数介绍 1、pipe 2、popen 3、pclose 4、注意 四、宏 五、常见的管道用法 1、一对一&#xff08;父进程读子进程写一条管道&#xff09; 2、一对一&#xff08;父进程写子进程读一条管道&#xff09; 3、一对多&#xff08;父进程…

leetcode—跳跃游戏—贪心算法

1 跳跃游戏1 给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&a…

vue-computed 计算属性

一、computed 计算属性 在Vue应用中&#xff0c;在模板中双向绑定一些数据或者表达式&#xff0c;但是表达式如果过长&#xff0c;或者逻辑更为复杂 时&#xff0c;就会变得臃肿甚至难以维护和阅读&#xff0c;例如&#xff1a; <div>写在双括号中的表达式太长了,不利于阅…

Linux 入门基础知识(一)—— Linux的基本使用

Linux 入门基础知识 一、Linux的基本使用和配置1.1、终端1.2、消耗内存1.3、运行级别1.6、登录前欢迎语1.5、登录后欢迎语1.6、shell1.7、ps aux1.8、设置主机名1.9、whoami和who am i1.10、命令提示符 二、Linux执行命令的过程详解和命令类型2.1、命令执行2.2、hash缓存表2.3、…

张维迎《博弈与社会》纳什均衡与囚徒困境博弈(2)囚徒困境博弈

囚徒困境大家应该都比较熟悉了&#xff0c;我觉得这篇的意义大概在与&#xff0c;经济学术语的运用&#xff1f; 囚徒困境&#xff1a;个人理性与集体理性的矛盾 假定有两个犯罪嫌疑人共同作案。警察抓住他们以后&#xff0c;分开拘押&#xff0c;并告诉他们&#xff1a;可以选…

Chiplet,汽车“芯”风向

异构集成、高速互联、算力灵活可扩展正在成为新一轮汽车芯片竞争的焦点。尤其是随着以ChatGPT为代表的大数据、大模型产品在车端的落地&#xff0c;对于芯片的要求还在持续提升。 本周&#xff0c;12家日本汽车制造商&#xff08;包括丰田、日产、本田等&#xff09;、零部件制…

设计与实现基于Java+MySQL的考勤发布-签到系统

课题背景 随着现代经济的迅速发展&#xff0c;电子考勤签到服务已经渗透到人们生活的方方面面&#xff0c;成为不可或缺的一项服务。在这个背景下&#xff0c;线上签到作为考勤签到的一种创新形式&#xff0c;为用户提供了便捷的操作方式&#xff0c;使得任务签到、个人签到记…

代码随想录算法训练营第35天 | 860.柠檬水找零 406.根据身高重建队列 452.用最少数量的箭引爆气球

柠檬水找零 局部最优&#xff1a;收到20元时优先找零10元5元&#xff0c;不够再找零3个5元&#xff0c;因为5元可以找零20和10&#xff0c;更有用。全局最优&#xff1a;完成所有的找零。 class Solution { public:bool lemonadeChange(vector<int>& bills) {int fi…

c++的发展史、缺省参数、命名空间你了解吗?

1.c的发展历史概述 1.1.什么是c C语言是结构化和模块化的语言&#xff0c;适合处理较小规模的程序。对于复杂的问题&#xff0c;规模较大的 程序&#xff0c;需要高度的抽象和建模时&#xff0c;C语言则不合适。为了解决软件危机&#xff0c; 20世纪80年代&#xff0c; 计算机…

TypeScript实战系列之强力爆破泛型的困扰

目录 介绍开始如何理解泛型语法泛型约束泛型默认值练习后续 介绍 泛型在typescript 中使用频率相当高&#xff0c;也给了初学者相当大的阻碍。希望这一篇文章&#xff0c;能帮助你们爆破它。 开始 下面通过模拟实现一个简易版本的axios来引入泛型的使用 // axios.ts type M…

如何在centos7上配置为桥接模式

一、打开虚拟机的设置页面&#xff0c;设置虚拟机桥接模式如图&#xff1a;选择桥接模式&#xff08;复制物理网络连接可选&#xff09; 二、net0对应桥接模式的配置&#xff0c;如下方式选择 三、 在 CentOS 7 中&#xff0c;通过编辑网络配置文件来配置网络参数。找到 /etc…