算法
JiaXianghao.
这个作者很懒,什么都没留下…
展开
-
链表相交的一系列问题
链表相交的一系列问题单链表可能有环,也可能无环。给定两个单链表的头节点head1和head2,这两个链表可能相交,也可能不相交。请实现一个函数,如果两个链表相交,请返回相交的第一个节点;如果不相交,返回null即可。要求:如果链表1的长度为N,链表2的长度为M,时间复杂度请达到O(N+M),额外空间复杂度请达到O(1)。第一步,我们需要判断给出的链表是不是有环的,如果有环,求出链表的入环节点...原创 2020-07-10 14:56:51 · 130 阅读 · 0 评论 -
贪心算法
贪心算法我脑补一些策略,并且写出一个非常暴力但是绝对对的方法,然后用对数器来跑这个。找到合适的策略,然后提交。因为OJ测试的时候数据量非常大,导致暴力方法会超时,时间被限制,提交通过以上的方法找到的那个策略是正确的。时间复杂度小。贪心策略正确性的证明千万不要去纠结。实际笔试或者面试的时候通过写对数器的方式来验证正确性。问题1:分金条的问题实质: 的问题。方法:实际解决这个问题的时候,...原创 2020-07-10 14:53:40 · 107 阅读 · 0 评论 -
链表的冒泡排序
对于一个数组结构我们一般都不会使用冒泡排序来做的,因为它的时间复杂度是O(N^2),但是为啥在链表身上我们想到了这一个排序呢?因为链表是无法以首地址加偏移的方式来进行操作的,但是却很容易在相邻两个元素之间进行比较。所以我们采用冒泡排序/************************************************************************* > F...原创 2020-02-21 16:09:35 · 604 阅读 · 0 评论 -
赋值运算符重载
#include <iostream>#pragma warning(disable : 4996)using namespace std;class CMyString{public: CMyString(char * pData = nullptr); CMyString(const CMyString& str); CMyString& ope...原创 2019-12-17 21:25:03 · 112 阅读 · 0 评论 -
LFU算法
#include <iostream>#include <unordered_map>using namespace std;class Node{public: Node(int key, int value, int times) { this->key = key; this->times = times; this->...原创 2019-12-28 20:16:19 · 4014 阅读 · 0 评论 -
判断一棵树是否为搜索二叉树
搜索二叉树其中序遍历是升序的,这里我们采用Morris遍历的方法来实现bool isBST(Node *head){ if (head == nullptr) { return true; } Node * cur1 = head; Node *cur2 = nullptr; Node * pre = nullptr; while (cur1 != nullptr) { ...原创 2019-12-27 16:33:03 · 110 阅读 · 0 评论 -
子数组的最大异或和
题目描述给定一个数组,求子数组的最大异或和一个数组的异或和为数组中所有的数异或起来的结果暴力解暴力解怎么搞?对于每个位置上的元素都要从0位置到当前位置开始遍历一遍,那么我们得到当前位置上元素的结果的时间复杂度是O(N2)的,对于每个位置我们都要求解,所以时间复杂度是O(N3)的时间复杂度。可以通过改变方向得到时间复杂度O(N^2)的算法示例代码:int maxEor(vector<...原创 2019-12-27 15:59:20 · 1156 阅读 · 0 评论 -
跳表
什么是跳表?跳表(skip list) 对应的是平衡树(AVL Tree),是一种插入/删除/搜索 都是 O(log n) 的数据结构。它最大的优势是原理简单、容易实现、方便扩展、效率更高。因此在一些热门的项目里用来替代平衡树,如 redis, leveldb 等。跳表的基本思想首先,跳表处理的是有序的链表(一般是双向链表,下图未表示双向),如下:这个链表中,如果要搜索一个数,需要从头到...转载 2019-12-26 17:19:23 · 532 阅读 · 0 评论 -
LRU算法
什么是LRU LRU是什么?按照英文的直接原义就是Least Recently Used,最近最久未使用法,它是按照一个非常著名的计算机操作系统基础理论得来的:最近使用的页面数据会在未来一段时期内仍然被使用,已经很久没有使用的页面很有可能在未来较长的一段时间内仍然不会被使用。基于这个思想,存在一种缓存淘...原创 2019-12-24 19:33:58 · 913 阅读 · 0 评论 -
树型DP
简介在二叉树上做动态规划其实要比其他结构上的动态规划要简单一些,因为他的步骤是相当固定的,从下面的例题中可以看出,例如求整棵树的最大搜索二叉子树,这里有一个非常简单的套路,那就是如果让我们求整棵树的最大搜索二茬子树,那么我们可以去求每一个节点的最大搜索二茬子树,最终答案必在其中。引子问题对于一棵二叉树,需要你求出它的最大值和最小值。解题思路方案一:直接遍历二叉树,那样就可以很轻松的获得...原创 2019-12-24 10:46:25 · 86 阅读 · 0 评论 -
在一个数组中,有零有正有负,给你一个目标值,求累加和为指定值的最长数组
解题思路如果遇到一个你看到子数组、子串这个问题,就是连续的一段,这样的问题,普遍的结题思路是,如果以每一个位置为结尾求出的答案,那么最终答案一定在其中。举例例如我们有角标从0到length-1这么多个数,指定的累加和为target,我们可以将每个数及其之前的数的和、该位置的角标作为一个键值对加入到map中,那么,当我们计算某一位置的最长子数组的时候,首先从map中获取到它到之前所有数的和su...原创 2019-12-23 10:54:22 · 199 阅读 · 0 评论 -
大楼轮廓问题
题意描述给定一个N行3列的二维数组,每一行表示有一座大楼,一共有N座大楼,所有大楼的地步都坐落在X轴上,每一行的三个值(a,b,c)代表每座大楼从(a,0)开始,到(b,0)点结束,高度为c,输入的数据可以保证a<b,且a,b,c均为正数,大楼之间可以重合,请输入整体轮廓线。例子:给定一个二维数组{{1,3,3},{2,4,4},{5,6,1}}输出轮廓线为{{1,2,3},{2,4,...原创 2019-12-23 09:51:29 · 215 阅读 · 0 评论 -
morris遍历
经典的二叉树遍历二叉树的遍历过程中,无论是递归的还是非递归的,都绕不过额外空间复杂度O(h), h为树的高度。因为我们在遍历完一棵子树之后希望能够回到父节点上,而经典的二叉树是没有指向父亲的指针的(实际工程上的红黑树中每个节点会有一个指向父的指针)。这就意味着从上级到下级容易,但是从下级到上级很难,于是我们就用到了栈,递归版本是递归函数帮助我们压栈,而非递归的版本是由我们自己做栈自己来压入,都省...原创 2019-12-21 11:51:39 · 227 阅读 · 0 评论 -
单调栈
解决什么问题 在一个数组中,我们想知道所有的数左边离他最近比他大(小)的和右边离他最近比他大(小)的,要求时间复杂度O(N)做到。暴力解 如果我们使用遍历的那种方法就会是O(N^2)。单调栈解法 &nbs...原创 2019-12-20 22:17:59 · 79 阅读 · 0 评论 -
可见山峰对问题
题意描述假设我给你一个数组代表一个环形的山,每个元素都代表一座山,每个座山上可以放烽火。两座山峰相互看见的前提:相邻的山必能相互看见烽火如果不相邻的两座山峰,只要存在一条路,这条路上的任意一个值都不大于路两头的山峰中较小值,就认为他们两座山可以相互看见预热阶段假设数组中所有的值都不一样,你要求所有能看见山峰对的数量,要求时间复杂度O(1)简单解法以下结论是在数组中所有值都不一样...翻译 2019-12-20 22:17:35 · 484 阅读 · 0 评论 -
求最大子矩阵的大小
引子问题寻找一个数组所代表的直方图中最大的长方形中包含多少个小正方形。对于下图所示的直方图中,结果为2*5=10引子问题思路 对于这个问题,我们的想法是对于直方图中每一列中最高的地方做一个标杆,然后看其向左向右分别能扩展到哪里,并记录小正方形的个数,能够出现的最大的正方形一定在这里面。具体的实现我们可以通过...原创 2019-12-20 21:32:03 · 165 阅读 · 0 评论 -
构造数组的MaxTree
题意描述一个数组的MaxTree定义如下,前提是数组没有重复元素,MaxTree是一棵二叉树,数组的每一个值对应一个二叉树节点。包括MaxTree树在内且在其中的每一棵子树上,值最大的节点都是数的头节点。对于没有重复元素的数组arr,写出生成这个数组的MaxTree的函数,要求如果 数组长度为N,则时间复杂度为O(N),额外空间复杂度为O(N)解法1我们可以把这个数组搞成堆,建立大跟堆的时...原创 2019-12-20 20:55:29 · 182 阅读 · 0 评论 -
窗口和窗口内最大值的更新结构
窗口 对于一个数组,我们有一个L来表示窗口的最左边,还有一个R来表示最右边。L和R只能向右移动,不能回退。L往右走是减数,R往右走就是加数,并且L也不能超过R。窗口内最大值的更新结构 如果你想要得到一个窗口的最大值,那么你当然可以...原创 2019-12-20 13:14:07 · 121 阅读 · 0 评论 -
BFPRT算法
问题引入希望你可以在一个无序数组中找到第k小的数,开始你的表演。方法1:我们可以采取排序的方式,但是这样就会产生一个O(NlogN)的代价。方法2:我们可以采取partation的过程,如果命中直接返回,否则看目标值在哪个区域,再次partition(快拍的改进)。虽然他不是BFPRT,但是已经足够优秀了。时间复杂度是基于概率的,长期的期望可以做到O(N),最好O(N),最差的时候为O(N^...原创 2019-12-19 16:53:29 · 441 阅读 · 0 评论 -
Manacher算法
用途马拉车算法讲的也是子串的问题,一个字符串中找到最大回文子串。暴力解分析暴力解法并不容易,因为你要解决长度为奇数和长度为偶数的不同情况。奇回文我们好搞,但是偶数回文就不那么简单了。如果是奇数个数:那么我们可以遍历字符串,对于其中任意一个字符,我们分别检查他的两侧。如果不是,那么就是1,如果是回文,就继续扩,最终得到回文的长度 。如果是偶数个数:…解法我们可以给字符串的两头以及字符中间...原创 2019-12-19 12:46:31 · 84 阅读 · 0 评论 -
KMP算法
什么是子串,什么是子序列?明确定义子序列不必是连续的。子串(数组)必须连续。笔试题中说让我们求子序列但往往他的含义就是子串,这样说是非常不好的。KMP用途解决子串包含问题,str1中是否包含str2,如果包含就返回str2开始的角标,否则返回-1。int getIndexof(str1, str2)这个函数其实就是使用的KMP的内容。但是在C++或者java中可能该方法是改进过的,但是基于...原创 2019-12-18 11:07:22 · 136 阅读 · 0 评论 -
打印子序列、全排列以及母牛问题
打印所有子序列子序列:子序列不要求所选的字母连续,只要求是按原有次序组成就行void printAllSub(string source, int index, string res){ if (source.size() == index) { cout << res << endl; return; } printAllSub(source, in...原创 2019-12-17 21:24:18 · 177 阅读 · 0 评论 -
动态规划
暴力递归把问题转化为规模缩小了的同类问题的子问题有明确的不需要继续进行递归的条件(base case)有当得到了子问题的结果之后的决策过程不记录每一个子问题的解动态规划从暴力递归中来将每一个子问题的解记录下来,避免重复计算把暴力 递归的过程抽象成了状态表达并且存在简化状态表达,使其更加简洁的可能什么样的问题可以从暴力递归改为动态规划在递归的时候有重复状态并且该问题是无...原创 2019-12-17 21:23:27 · 97 阅读 · 0 评论 -
前缀树
结构:经典的实现就是字母放在边上。而不是节点中。创建方法:一个字符串加入的时候,总是从头节点开始,依次看有没有沿途的路,如果有复用,如果没有就建出来。前缀树中加入了“abc”之后的样子再加入“abd”再加入"bce"用途:当我们向前缀树中加入了很多字符串之后我想问问你现在有没有以某一个字符串开始的?不能进行遍历。是否加入过某个字符串,加过几次?。(或者每个节点加上一个数据项...原创 2019-12-16 22:20:23 · 81 阅读 · 0 评论 -
并查集的应用(岛问题)
题意描述一个矩阵中只有0和1两种值,每个位置都可以和自己的上、下、左、右四个位置相连,如果有一片1连在一起,这个部分叫做一个岛,求一个矩阵中有多少个岛?举例:1,1,0,11,0,1,00,1,1,1共有三个岛。解决方案常规解法我们可以设计一个感染函数,该函数的功能是如果当前位置是1,那么会将该位置的值修改为2,并且对上下左右递归调用。示例代码#include <ios...原创 2019-12-16 10:10:05 · 123 阅读 · 0 评论 -
并查集
用处1)快速的检查两个元素是否属于一个集合。2)两个元素(参数)各自所在的集合,请你把他们合并在一起满足以上用处的其他实现1)搞成列表(Node),判断是否在同一集合的时候需要进行遍历(代价高)。合并的代价就小些。2)做成哈希表,如果是判断是否是同一个集合O(1),但是如果合成两个集合就是遍历行为(代价高)。落地结构每个元素有一个数据域和一个指针域。让每个元素自成集合(即指针指向自己...原创 2019-12-15 16:15:19 · 149 阅读 · 0 评论 -
二叉树的遍历
先序遍历是指,先打印当前节点,再打印左子树上所有节点,打印完左子树上所有节点之后再打印右子树上所有节点。中序遍历是指,先打印左边的节点,再打印当前节点,最后打印右边节点。后序遍历是指,先打印左边的节点,在打印右边节点,最后打印中间节点。不论是递归版还是非递归版,时间复杂度是O(N)(节点的个数),额外空间复杂度是二叉树的高度,递归中使用递归栈也要占用空间的。我们后面是可以做到O(1)Morr...原创 2019-12-15 14:44:15 · 79 阅读 · 0 评论 -
在数组中找到一个局部最小的位置
题意描述定义局部最小的概念。arr长度为1时,arr[0]是局部最小。arr的长度为N(N>1)时,如果arr[0]<arr[1],那么arr[0]是局部最小;如果arr[N-1]<arr[N-2],那么arr[N-1]是局部最小;如果0<i<N-1,既有arr[i]<arr[i-1],又有arr[i]<arr[i+1],那么arr[i]是局部最小。给定...原创 2019-12-15 12:07:08 · 239 阅读 · 0 评论 -
priority_queue
头文件首先使用priority_queue必须要包含的头文件是queue,它和普通的队列一样都有empty方法、size方法、top方法、push方法、pop方法,在此不再赘述。主要着重探讨priority_queue与queue的不同之处。priority_queue原型template <class T, class Container = vector<T>, c...原创 2019-12-15 11:40:31 · 116 阅读 · 0 评论 -
随时找到数据流的中位数
随时找到数据流的中位数堆结构优先级队列的底层就是堆。加入之后会进行小根堆的调整。弹出的时候从堆顶开始谈。默认是小根堆。增查都是O(logN)二叉树的高度。方法:使用两个堆,保证假设排序之后前一半在大跟堆,后一半在小根堆。如果两个堆的大小相差两个及以上,将数量较大的那个堆中的堆顶元素放入到另一个堆中。如果我们收集到数据之后排序,效率是很慢的。调整堆结构的代价是log(N)级别的。得到中位...原创 2019-12-15 11:00:25 · 295 阅读 · 0 评论 -
拷贝含有随机指针的链表
题意描述Node类中的value是节点值,next指针和正常单链表中next指针的意义一样,都指向下一个节点,rand指针是Node类中新增的指针,这个指针可能指向链表中的任意一个节点,也可能指向null。给定一个由Node节点类型组成的无环单链表的头节点head,请实现一个函数完成这个链表中所有结构的复制,并返回复制的新链表的头节点。struct Node{ Node(int value...原创 2019-12-14 16:36:54 · 121 阅读 · 0 评论 -
链表partition
题意描述给定一个单向链表的头节点head,节点的值类型是整型,再给定一个整数pivot。实现一个调整链表的函数,将链表调整为左部分都是值小于pivot的节点,中间部分都是值等于pivot的节点,右部分都是值大于pivot的节点。除这个要求外,对调整后的节点顺序没有更多的要求。例如:链表9->0->4->5->1,pivot=3。调整后链表可以是1->0->4...原创 2019-12-14 15:47:33 · 496 阅读 · 0 评论 -
判断某链表是否为回文结构
题目给定一个链表的头节点head,请判断该链表是否为回文结构。例如:1->2->1,返回true。1->2->2->1,返回true。15->6->15,返回true。1->2->3,返回false。方案1我们可以先弄一个栈,遍历链表将所有东西都压入到栈中,第二次遍历时,每遍历一个元素,我们就从栈中取一个元素比对,如果一样对比下一...原创 2019-12-14 14:06:10 · 494 阅读 · 0 评论 -
设计RandomPool结构
题目请设计RandomPool结构,使其具有以下三个功能:将某个key加入到该结构,做到不重复加入将原本在结构中的某个key移除。等概率随机返回结构中的任意一个Key要求:以上三个方法的时间复杂度是O(1)的分析:第一个方法要求不重复加入以及要求中的时间复杂度为O(1)使得我们联想到了哈希表。考虑到第三个问题中要求我们随机返回一个key,我们就想到了rand方法以及为每个key都加...原创 2019-12-14 11:37:16 · 97 阅读 · 0 评论 -
打印链表的公共部分
打印两个有序链表的公共部分题目描述给定两个有序链表的头指针head1和head2,打印两个链表的公共部分。解法1我们可以使用哈希set,将其中一条链表中所有节点压入,然后遍历另外一条链表,每遍历一个节点就看看该值是否已经在哈希set中了。示例代码解法2使用外排的思想,谁小动谁,如果相等就同时都动,如果有一个链表越界,那么就结束这个流程。...原创 2019-12-14 11:33:48 · 153 阅读 · 0 评论 -
在行列都排好序的矩阵中找数
题目描述给定一个有N*M的整型矩阵matrix和一个整数K,matrix的每一行和每一列都是排好序的。实现一个函数,判断K是否在matrix中。例如:0 1 2 52 3 4 74 4 4 85 7 7 9如果K为7,返回true,如果K为6,返回false。要求时间复杂度为O(N+M),额外空间复杂度为O(1)思路我们可以选择左下角或者是右上角的元素作为开始,这样每处于一个位...原创 2019-12-13 23:12:41 · 105 阅读 · 0 评论 -
转圈打印矩阵以及之字打印矩阵
这两道题目的目的就是训练我们应该由宏观调度的概念,切不可注重于局部的变化。相同点:a) 这些题没告诉你怎么做好,告诉你不能怎么做。不能想下标怎么变化!!!。b) 先要确定好宏观调度,然后其他的都是简单函数转圈打印矩阵题目给定一个整型矩阵matrix,请按照转圈的方式打印它。例如:1 2 3 &...原创 2019-12-13 22:53:50 · 95 阅读 · 0 评论 -
栈和队列之间的转换
关键点:当我们从Push栈中把数据倒入Pop栈中的时候要注意时机1) POP栈中如果有东西一定不要倒。2) POP栈为空再倒,PUSH中不能留东西。class StackToQueue{public: //我们并没有忘记提供构造和析构函数,系统默认提供的方法可能有更高的效率 void push(int pushInt) { stackPush.push(pushInt); }...原创 2019-12-11 09:10:28 · 87 阅读 · 0 评论 -
最小栈设计
实现一个特殊的栈,在实现栈的基本功能的基础上,再返回栈中最小元素的操作。要求:pop、push、getMin操作的时间复杂度都是O(1)设计的栈类型可以使用现成的栈结构我们有两种方案,这两种方案都是封装一个用于存放数据的栈,一个用来存放曾经出现过的最小值的栈。只不过其压入方式不同。class GetMinStack1{public: GetMinStack1() { ...原创 2019-12-11 08:34:29 · 194 阅读 · 0 评论 -
固定数组实现队列
设插入数据的位置是end,取出数据的位置是start在实现队列的时候,我们不应该考虑让end和start相互耦合到一块,这样会导致问题更加复杂,比如他们的起始位置,以及怎么判断队列是空OR队列是满?解决方案:我们添加一个变量用来指示当前栈中元素的个数(length),通过该变量解耦start和end。再编写代码就比较简单了。。#include <iostream>#includ...原创 2019-12-10 23:04:08 · 135 阅读 · 0 评论