算法随笔
记录学习算法过程中的笔记、想法、题目
RJ_theMag
这个作者很懒,什么都没留下…
展开
-
记水题两道
1输入一个十进制整数,输出对应的七进制结果.例如:Input1:20Output1:26Input2:-100Output2:-202题解:根据辗转相除法,输入 num,每次将 num 对 7 取余,再将 num 除 7,直到 num 为 0 为止,得到的余数加入到一个字符串中,对这个字符串翻转之后就是 num 对应的 7 进制数.特别注意一下对正负号的处理.C++ code:#include <bits/stdc++.h>using namespa原创 2022-04-24 00:08:54 · 1161 阅读 · 0 评论 -
浮点数二分
和整数二分不同,浮点数不存在由于(整数)取整导致的边界问题,每次二分区间严格减半,因此比整数二分简单的多,每次更新边界时直接让r = mid或l = mid即可。看一道题,acwing790.数的三次方根浮点数二分除了更新区间和浮点数不同,还有就是二分终止条件,一般有两种写法,一种就是当前区间长度已经足够小。比如这题需要保留六位小数,我们可以在区间长度小于1e-8时结束循环,一般区间长度比保留位数还要小两个数量级。#include<iostream>using namespace原创 2020-08-11 16:55:48 · 1605 阅读 · 3 评论 -
[模板]整数二分
整数二分有两个模板。int bsearch_1(int l, int r) { while(l < r) { int mid = l + 1 >> 1; if(check(mid)) r = mid; else l = mid + 1; } return l;}这种写法每次把区间压缩到**[l, mid]或[mid + 1, r]**。int bsearch_2(int l原创 2020-08-11 16:45:35 · 168 阅读 · 0 评论 -
[模板]归并排序
原题链接:acwing787.归并排序归并排序和快速排序类似,都是基于分治的,步骤如下:(1)确定待排序数组的分界点mid, 一般取mid为待排序数组的中位数 mid = l + r >> 1;(2)递归排序分界点的左右两侧区间,直到区间大小为1;(3)归并两个排好序的区间,把两个有序的数组合二为一,最后合并好的数组就是排好序的数组。归并的方法是双指针。左右区间排好序的数组分别为left和right,我们开一个额外的,大小与原数组大小相等的数组tmp记录最后排好序的结果。用两个指原创 2020-08-11 14:28:49 · 152 阅读 · 0 评论 -
快速排序题一道
原题链接:acwing786.第k个数一道快速排序的模板题,关于快速排序的原理和模板,可以参考[模板]快速排序这里直接贴代码吧,和模板没什么区别,就输出排序后的第k个数而已。#include<iostream>using namespace std;const int N = 1e6 + 10;int q[N];void quick_sort(int q[], int l, int r) { if(l >= r) { return ; }原创 2020-08-11 11:35:37 · 118 阅读 · 0 评论 -
[模板]快速排序
原题链接:acwing785.快速排序给定数组大小n和数组q[n],对数组进行排序。快速排序的原理:基于分治(1)确定分界点x:可以取x为q[l], q[l + r >> 1],q[r], 或者数组中间随机一个值(建议取q[l + r >> 1], 原因在后面说)。这里l和r是当前待排序数组的左右端点。(2)重新调整区间,使得调整后的区间,小于等于x的数都在x的左边,大于等于x的数都在x的右边(和x相等的数在左边、右边都可)。 调整区间的方法有两种,后面说。(3)递归处理原创 2020-08-11 11:20:57 · 65 阅读 · 0 评论 -
LeetCode85. 最大矩形
这题其实是84题的进阶版。要求最大矩形,同样也是枚举所有矩形,关键就在于如何枚举。如果直接枚举所有起点和终点,复杂度最起码是O(n^4),超时。所以要换种方式枚举,可以考虑固定住所有矩形的底边,比如以每一行作为底边,枚举以这个底边,往上有哪些矩形,分别计算面积。固定住底边之后,网上所有的连续的’1’就构成了类似84题的柱状图,84题我们已经用单调栈在O(n)时间内解决了,枚举所有底边(行数)也需要O(n),所以总的时间复杂度是O(n^2)。因为原数组是字符数组,所以我们要预处理一下高度,额外.原创 2020-07-17 11:59:39 · 166 阅读 · 0 评论 -
单调栈
原题链接这道题就是单调栈最经典的应用,单调栈往往就是求一个数组中每个元素左边(之前)的元素中离它最近的比它小的元素。首先很容易想到暴力做法,对于每一个元素,从当前元素的前一个元素开始往前遍历,第一个满足小于当前元素的元素就是答案,遍历完数组都不存在元素比当前元素小,则输出-1.代码如下:#include<bits/stdc++.h>using namespace std;const int N = 1e5 + 5;int a[N];int main() { int .原创 2020-07-16 19:54:35 · 89 阅读 · 0 评论 -
数组模拟队列
原题链接数组模拟队列和数组模拟栈其实很类似,都是用一个数组来存储元素,用指针表示当前可以操作的位置。区别就是栈只能在栈顶进行操作,所以只需要有一个top指针指向栈顶。而队列可以在队头和队尾都进行操作(出队、入队),所以需要两个指针head和tail指向队头和队尾。如果有元素入队,则tail加一,指向新元素。如果要出队,则head加一,指向原来队列的第二个元素,这个元素就是现在的对头。具体代码如下:#include<bits/stdc++.h>using namespace s..原创 2020-07-16 13:39:37 · 88 阅读 · 0 评论 -
数组模拟栈
原题链接题意是用数组模拟一个栈,支持四种栈操作:在栈顶插入元素,弹出栈顶元素,查询栈顶元素,查询栈是否为空。用数组模拟栈只需要开一个数组存储栈元素,再用一个额外的变量top表示当前栈顶元素下标。直接看代码吧:#include<bits/stdc++.h>using namespace std;const int N = 1e5 + 5;int stk[N], top; //栈数组和栈顶下标void init() { top = 0; ..原创 2020-07-16 13:26:08 · 113 阅读 · 0 评论 -
数组实现双链表
之前写了数组实现单链表,提到了数组实现链表比指针实现最大的优点就是快,可以随机存取,而且不用new节点。在图论的题目里用到邻接表,往往都是用数组实现。数组实现双链表比单链表就多了一些对于左指针的操作。为了实现的方便,不像在单链表实现里用一个额外的变量head去记录链表的头节点。而是直接用两个哨兵节点固定为双链表的头节点和尾节点。我们可以固定头节点为0,尾节点为1.也就是说,0的right指针指向链表的第一个节点,1的left指针指向链表的第一个节点。这样,0和1就被固定为头节点和尾节点了。我们原创 2020-07-16 13:13:12 · 714 阅读 · 0 评论 -
数组实现单链表
单链表常见的实现方法有两种,一种方式是定义一个结构体表示链表节点。比如:struct node{ int val; node* next;};然后就是通过next指针将链表的所有节点连接起来。如果涉及到链表节点的插入和删除操作,则只需要修改链表节点的指针即可。这种方式有个明显的缺点,就是不能随机存取。如果要在某个节点之后插入或者删除节点,复杂度是O(n),因为要从头开始逐个遍历到需要插入或者删除的节点(通过next指针找)。所以用结构体实现的单链表缺点就是太慢了。当然还有一原创 2020-07-15 20:33:48 · 1543 阅读 · 1 评论 -
链表题目一道
原题链接来源:剑指offer, Hulu面试题题意很简单。给定一个单链表,反转这个单链表,返回翻转后的头节点。方法一 借助栈的性质要将链表翻转,很容易想到借助栈的后进先出的性质来改变链表的顺序。将链表节点顺序压入栈中,链表节点全部进栈以后,取栈顶元素作为新链表的头节点,然后将元素不断出栈,每出栈一个元素就连接到新链表的末尾。时间复杂度:将链表元素压入栈中需要遍历一次链表,将栈中所有元素连接起来需要遍历一遍栈,时间复杂度是O(n).空间复杂度:需要额外开一个栈存放所有元素,空间复杂度是O(n).原创 2020-07-10 11:11:40 · 319 阅读 · 2 评论