
数据结构
文章平均质量分 63
傅-圣
技术向轮子哥看齐,产品向张小龙看齐
展开
-
数据结构之跳跃表
打算把【数据结构】整理成一系列博客,今天写的是【跳跃表】(skiplist) 定义:跳跃链表是一种数据结构,允许快速查询一个有序连续元素的数据链表。快速查询是通过维护一个多层次的链表,且每一层链表中的元素是前一层链表元素的子集。效率和平衡树媲美 —— 查找、删除、添加等操作都可以在O(log n)期望时间下完成, 并且比起平衡树来说, 跳跃表的实现要简单直观得多。基本上,跳跃列表是对...原创 2017-11-13 09:13:43 · 796 阅读 · 0 评论 -
数据结构之栈
今天我们继续聊聊栈(Stack)栈:栈是一种线性存储结构,它有以下几个特点:(01) 栈中数据是按照"后进先出(LIFO, Last In First Out)"方式进出栈的。(02) 向栈中添加/删除数据时,只能从栈顶进行操作。(下图来源于网络)其实在现实生活中,有很直观的例子。比如,你把几本书从下往上叠,如果想要拿出书,肯定是先把上面的书拿开,才可以拿到下面原创 2017-11-13 14:59:26 · 190 阅读 · 0 评论 -
《剑指offer》(面试题10):二进制中1的个数
位运算位运算是把数字用二进制表示之后,对每一位上 0 或者 1 的运算。因为位运算总共只有五种运算:与,或,异或,左移和右移与(&) 0&0=0 1 & 0 = 0 0 & 1 = 0 1 & 1 = 1或(|) 0 | 0 = 0 1 | 0 = 1 0 | 1 = 1 1 | 1 = 1异或(^原创 2018-01-31 11:44:02 · 184 阅读 · 0 评论 -
《剑指offer》(第三章):高质量的代码
总结:一般会考查代码的容错处理能力,对一些特别的输入会询问应聘人员是否考虑,如何处理。不能容忍diamante只是针对一种假想的 “正常值” 进行处理,不考虑异常情况,也不考虑资源的回收等问题。书写,布局和命名都决定着代码的规范性。从功能测试,边界测试,负面测试3个方面设计测试用例,以保证代码的完整性。首先考虑的是普通功能测试的测试用例。考虑功能测试原创 2018-02-01 17:53:03 · 185 阅读 · 0 评论 -
《剑指offer》(面试题11):数值的整数次方
题目描述给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。解题思路方法一:公式求解我们知道当指数为负数的时候,可以先对指针求绝对值,然后算出次方的结果之后再取倒数。如果要自己实现,那么就需要考虑各种错误处理和边界问题。比如,既然有求倒数,对0求倒数怎么办,当底数是0且指数是负数的时候,如果不做特殊处理,就会原创 2018-02-01 18:08:22 · 190 阅读 · 0 评论 -
《剑指offer》(面试题13):在O(1)时间删除链表结点
题目:给定单向链表的头指针和一个结点指针,定义一个函数在 O(1)时间删除该结点。之所以需要从头开始查找,是因为我们需要得到将删除的结点的前面一个结点。在单向链表中,结点中没有指向前一个结点的指针,所以只好从链表的头结点开始顺序查找。我们可以很方便地得到要删除的结点的下一结点。如果我们把下一结点的内容复制到需要删除的结点上覆盖原有的内容,再把下一个结点删除,那是不是就相当于原创 2018-02-01 18:35:27 · 246 阅读 · 0 评论 -
《剑指offer》(面试题14):调整数组顺序使奇数位于偶数前面
总结:考虑可扩展性的解法,能秒杀 offer面试官期待我们提供的不仅仅是解决一个问题的办法,而是解决一系列同类型问题的通用办法。这就是面试官在考查我们对扩展性的理解。题目描述输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。解题思路方法一原创 2018-02-01 20:05:48 · 205 阅读 · 0 评论 -
《剑指offer》(面试题15):链表中倒数第k个结点
代码的鲁棒性(robust)提高代码的鲁棒性的有效途径是进行防御性编程。其实也是一种编程习惯,是指预见在什么地方可能会出现问题,并为这些可能出现的问题制定处理方式。比如试图打开文件时发现文件不存在,我们可以提示用户检查文件名和路径;在面试时,最简单的防御性编程就是在函数入口添加代码已验证用户输入是否符合要求。我们需要格外关注这些函数的输入参数。如果输入的是一个指针,那指针是转载 2018-02-01 20:32:00 · 145 阅读 · 0 评论 -
(未完成)《剑指offer》(面试题16):反转链表
题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。以这道题为例,我们至少应该想到几类测试用例对代码做功能测试:输入的链表头指针是 NULL。输入的链表只有一个结点。输入的链表有多个结点。原创 2018-02-01 20:54:13 · 191 阅读 · 0 评论 -
《剑指offer》(面试题17):合并两个排序的链表
在面试过程中,最容易犯两种错误:一是在写代码之前没有对合并的过程想清楚,最终合并出来的链表要么中间断开了要么并没有做到递增排序;二是代码在鲁棒性方面存在问题,程序一旦有特殊的输入(如空链表)就会崩溃。题目描述输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。解题思路递归:新创建一个指针就可以,比较两个链表的值,然后做相应转载 2018-02-01 22:20:06 · 174 阅读 · 0 评论 -
(未完成)《剑指offer》(面试题18):树的子结构
在面试的时候,我们一定要注意边界条件的检查,即检查空指针。当树 A 或树 B 为空的时候,定义相应的输出。可以分成两步:第一步在树 A 中找到和 B 的根结点的值一样的结点 R,第二步再判断树 A 中以 R 为根节点的子树是不是包含和树 B 一样的结构。原创 2018-02-01 22:46:48 · 161 阅读 · 0 评论 -
《剑指offer》(面试题21):包含min函数的栈
前言:当一眼看不出问题中隐藏的规律的时候,我们可以试着用一两个例子模拟操作的过程,这样说不定就能通过具体的例子找到抽象的规律。可以举出一两个例子,告诉面试官问的算法是怎么一步步处理这个例子的。模拟压栈和弹出几个数字,分析每次操作之后数据栈,辅助栈和最小值是什么?怎么检查代码呢?可以运行几个测试用例。题目描述定义栈的数据结构,请在该类型转载 2018-02-02 17:44:01 · 211 阅读 · 0 评论 -
《剑指offer》(面试题23):从上往下打印二叉树
前言:当一眼看不出问题中隐藏的规律时,我们可以试着用一两个具体的例子模拟操作的过程,说不定这样那就能通过具体的例子找到抽象的规律。题目描述从上往下打印出二叉树的每个节点,同层节点从左至右打印。解题思路再熟悉不过的层序遍历,BFS即可实现。用队列来进行层序遍历,同时用一个vector容器来存储每一层的值。举例如下:python 代码转载 2018-02-02 17:55:40 · 237 阅读 · 0 评论 -
《剑指offer》(面试题24):二叉搜索树的后序遍历序列
前言:当一眼看不出问题中隐藏的规律时,我们可以试着用一两个具体的例子模拟操作的过程,说不定这样那就能通过具体的例子找到抽象的规律。题目描述输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。解题思路深度优先遍历中的先序遍历、中序遍历、后序遍历,都是针对在遍历中根结点的位转载 2018-02-02 18:12:34 · 231 阅读 · 0 评论 -
《剑指offer》(面试题27):二叉搜索树与双向链表
前言在计算机领域有一类算法叫分治法,即“分而治之”。采用的就是各个击破的思想,我们把分解后的小问题各个解决,然后把小问题的解决方案结合起来解决大问题。题目描述输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。解题思路哇偶,中序遍历啊!中序遍历,递归和循环都可以撒~二叉搜索树是一种排序转载 2018-02-02 18:37:44 · 240 阅读 · 0 评论 -
《剑指offer》(面试题9):斐波那契数列
前言如果我们需要重复地多次计算相同的问题,通常可以选择用递归或者循环两种不同的方法。递归式在一个函数的内部调用这个函数自身。而循环则是通过设置计算的初始值及终止条件,在一个范围内重复运算。通常递归的代码会比较简洁。在面试的时候,如果面试官没有特别的要求,应聘者可以尽量多采用递归。递归虽然有简介的优点,但它同时也有显著的缺点,那就是时间和空间的消耗:每一次函数调用,都需要原创 2018-01-31 11:00:43 · 283 阅读 · 0 评论 -
(未完成)《剑指offer》(面试题8):旋转数组的最小数字
其中排序和查找是面试时考察算法的重点。在准备面试的时候,我们应该重点掌握二分查找,归并排序和快速排序,做到能随时正确,完整地写出他们的代码。如果面试题是要求在排序的数组(或者部分排序的数组)中查找一个数字或者统计某个数字出现的次数,我们都可以尝试用二分查找算法。查找相对而言较为简单,不外乎顺序查找,二分查找,哈希表查找和二叉排序树查找。排序比查找要复杂一些。原创 2018-01-31 10:50:02 · 271 阅读 · 0 评论 -
数据结构之哈希表(Hash Table)(未搞定)
今天我们来聊聊哈希表。哈希表(Hash Table,也叫散列表):散列表(Hash table,也叫哈希表),是依据关键码值(Key value)而直接进行訪问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来訪问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。(来自维基百科)哈希表的实现主要需要解决两个问题:哈希函数和哈希冲突。原创 2017-11-20 20:31:47 · 247 阅读 · 0 评论 -
堆排序
今天我们来聊聊堆排序。在介绍堆排序之前,首先需要介绍一下【堆】堆是一颗顺序存储的完全二叉树。其中每个结点的关键字都不大于其孩子结点的关键字,这样的堆称为小跟堆。其中每个结点的关键字都不小于其孩子结点的关键字,这样的堆称为大根堆。如上图所示,序列R{3, 8, 15, 31, 25}是一个典型的小根堆。设当前元素在数组中以 R[i] 表示,那么原创 2017-12-14 22:43:26 · 179 阅读 · 0 评论 -
数据结构之队列
今天我们要聊的是 队列(Queue)队列(Queue):(01) 队列中数据是按照"先进先出(FIFO, First-In-First-Out)"方式进出队列的。(02) 队列只允许在"队首"进行删除操作,而在"队尾"进行插入操作队列也是一种线性表,很形象的比喻就是像排队一样,刚来的人入队(push)要排在队尾(rear),每次出队(pop)的都是队首(front)原创 2017-11-13 13:02:44 · 208 阅读 · 0 评论 -
单词查找树
今天我们俩聊聊 Trie树(字典树)。Trie树,即字典树,又称单词查找树或键树,是一种树形结构。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是最大限度地减少无谓的字符串比较,查询效率比较高。Trie的核心思想是空间换时间,利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。它有3个基本性质:根节点不包原创 2017-12-09 23:45:36 · 539 阅读 · 0 评论 -
倒排索引
今天我们来聊聊倒排索引(inverted index)。倒排索引是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射,常被应用于搜索引擎和关键字查询的问题中。以英文为例,下面是要被索引的文本:T0 = "it is what it is" T1 = "what is it" T2 = "it is a banana" 我们就原创 2017-12-18 17:38:32 · 189 阅读 · 0 评论 -
布隆算法(微信公众号)
今天我们来聊聊布隆算法。爬虫的原理就不细说了,无非是通过种子 URL 来顺藤摸瓜,爬取出网站关联的所有的子网页,存入自己的网页库当中。爬取出来的 URL 有可能存在重复,需要被丢弃掉,如何实现 URL 的去重呢?URL去重方案第一版:HashSet创建一个HashSet集合,把每一个URL字符串作为HashSet的key插入到集合当中,利用HashSet原创 2017-12-14 20:56:30 · 281 阅读 · 0 评论 -
《剑指offer》(面试题4):替换空格
题目描述请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。看到这个题目,我们首先应该想到的是原来一个空格字符,替换之后变成'%','2'和'0'这 3 个字符,因此字符串会变长。如果是在原来的字符串上做替换,那么就有可能覆盖修改在该字符串后面的内存。如果是创建新的字符串并在新的字原创 2018-01-30 21:36:58 · 177 阅读 · 0 评论 -
《剑指offer》(面试题3):二维数组中的查找
题目描述在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。解题思路首先选取数组中右上角的数字。如果该数字等于要查找的数字,查找过程结束;如果该数字大于要查找的数字,剔除这个数字所在的列;如果该数字小于要查找的数字,剔除这个数字所在的行。也就原创 2018-01-28 23:29:30 · 217 阅读 · 0 评论 -
python 之字符串(没搞定)
题目:替换空格题目描述请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。时间复杂度为O(n^2)的解法最直观的做法是从头到尾扫描字符串,每一个碰到空格字符的时候做替换。由于是把1个字符替换成3个字符,我们必须要把空格后面所有的字符都后移两个字节,否则就有两个字原创 2018-01-23 21:12:29 · 325 阅读 · 0 评论 -
数据结构之数组跟链表
今天我们来聊聊数组跟链表,是非常基础的数据结构。数组:数组是无序的元素序列。示例如下:int[] arr = {10, 20, 30, 40, 50}数组的特点是:元素地址是连续的,随机访问速度快。链表(linked list):链表(linked list)是由一组被称为结点的数据元素组成的数据结构,每个结点都包含结点本身的信息和指向下一个结点的地址。由于每个结点原创 2017-11-17 09:38:46 · 357 阅读 · 0 评论 -
二叉树(是未完成)
今天我们来聊聊二叉树。(性质可以收集起来)(1)在二叉树的第 i 层上至多有 2的(n-1)次方个结点(2)深度为 k 的二叉树至多有 2的 k 次方-1 个结点(3)具有 n 个结点的完全二叉树的深度为【n的对数】+1二叉链表来储存每个结点。(这个也是,写出自己的思考逻辑)前序遍历:先访问“根结点”,然后前序遍历左子树,再前序遍原创 2017-11-23 08:59:18 · 278 阅读 · 0 评论 -
《剑指offer》(面试题5):从头到尾打印链表
题目描述输入一个链表,从尾到头打印链表每个节点的值。如果可以修改原来链表的结构,那么把链表中链接结点的指针反转过来,改变链表的方向,然后就可以从头到尾输出了。但是,打印通常是一个只读操作,我们不希望打印时修改内容,所以就得想别的办法。循环接下来我们想到解决这个问题肯定要遍历链表。顺序是从头到尾的顺序,可输出的顺序确实从尾到头。也就是说第一个遍历到的结点最原创 2018-01-30 21:56:09 · 256 阅读 · 0 评论 -
《剑指offer》(面试题6):重建二叉树
面试的时候提到的树,大部分都是二叉树。所谓二叉树是树的一种特殊结构,在二叉树中每个结点最多只能有两个子结点。在二叉树中最重要的操作莫过于遍历,即按照某一顺序访问树中的所有结点。通常树有如下几种遍历方式:前序遍历:先访问根结点,再访问左子结点,最后访问右子结点。中序遍历:先访问左子结点,再访问根结点,最后访问右子结点。后序遍历:先访问左子结点,再访问右子结点,最后访问根结点。特例原创 2018-01-31 10:07:32 · 152 阅读 · 0 评论 -
《剑指offer》(面试题7):用两个栈实现队列
题目描述:用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。解题思路:栈:后进先出(LIFO); 队列:先进先出(FIFO). 入队:将元素进栈A 出队:判断栈B是否为空,如果为空,则将栈A中所有元素pop,并push进栈B,栈B出栈; 如果不为空,栈B直接出栈python 代码实现:# -*- coding:utf原创 2018-01-31 10:13:46 · 173 阅读 · 0 评论 -
《剑指offer》(面试题34):丑数
题目描述把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。解题思路同样的,我们首先想到的可能就是遍历判断,但是每个数都要计算一次是不是ugly,很是麻烦。于是我们想,能不能只对ugly进行计算呢,显然是可以的。我们用一个数组来从小到大存转载 2018-02-03 11:49:32 · 372 阅读 · 0 评论