剑指数据结构与算法
探索数据结构的奥秘,没有最好只有最清晰,适合的才是最好的!烫!烫!烫!
RhythmWANG
看体育、玩音乐,碰巧考上了大学,碰巧是个攻城狮……
展开
-
二维数组中的查找
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。理解:该题目的一大线索是数组中的值进行了从左到右,从上到下的排序,要充分利用这种排序的结果,不要直接去一个一个的对比。 将行、列的坐标定位到矩阵的右上角,当小于target的时候继续向下一列来对比,当大于的时候说...原创 2018-07-09 14:18:23 · 219 阅读 · 0 评论 -
替换空格
剑指offer第2题: 请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。理解:本题的重点是把StringBuffer用好,这是一个字符串变量类型,使用它可以通过调用append方法便捷地对字符串进行加工。 建立一个新的字符串StringBuffer。通过检测是否为空格来...原创 2018-07-10 17:50:12 · 199 阅读 · 0 评论 -
从尾到头打印链表
剑指offer第3题: 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。理解:本题中的关键词是从尾到头,考察当遇到反向输出时是否可以想到使用堆栈特性来辅助输出。 现将所有节点都压入堆栈,然后再依次弹出,此时弹出的顺序就是从尾到头的顺序了。注意ArrayList中存放的是整型,而不是ListNode型,这点要注意,否则是错的。import java.u...原创 2018-07-16 22:03:39 · 170 阅读 · 0 评论 -
重建二叉树
剑指offer第4题: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。理解:本题首先应当理解前序遍历和中序遍历是什么,这里的“前”和“中”都是指遍历根节点的次序,前序遍历是先遍历根节点,中...原创 2018-07-17 10:01:52 · 212 阅读 · 0 评论 -
用两个栈实现队列
剑指offer第5题: 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。理解:完成本题首先应当理解堆栈和队列的关键性质。堆栈是先入后出,FILO;而队列是先入先出,FIFO。 当有元素需要进入队列就将其压入Stack1,当有元素需要出队列,就将Stack1中的元素全部弹出到Stack2中,通过Stack2来负责出队列。Stack1负责入,...原创 2018-07-17 10:52:50 · 152 阅读 · 0 评论 -
旋转数组的最小数字
剑指offer第6题: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。理解:一种方法是用二分法,找到mid,然后通过对比mid与left,right...原创 2018-07-17 12:08:04 · 197 阅读 · 0 评论 -
斐波那契数列
剑指offer第7题: 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。(n<=39)理解:本题没有太大的难度,需要了解斐波那契数列的计算规则。按照规则第0项为0,第一项和第二项为1,后面按照规则相加计算即可。注意处理好for循环的循环边界。public class Solution { public...原创 2018-07-17 20:03:39 · 186 阅读 · 0 评论 -
跳台阶
剑指offer第8题: 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。理解:本题是斐波那契数列的变形,可以参考斐波那契数列计算的试题。只需要将台阶的级数对应斐波那契数列的第几个数对应对就好。第一阶台阶对应的是斐波那契的第二项1,第二阶台阶对应数列的第三项2。public class Solution ...原创 2018-07-17 20:20:01 · 175 阅读 · 0 评论 -
变态跳台阶
剑指offer第9题: 一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。理解:本题的重点是知道一共是2^(n-1)种情况。直接用公式即可,使用左移来做2的次方,这里显得更加清晰。public class Solution { public int JumpFloorII(int target) {...原创 2018-07-17 20:28:21 · 212 阅读 · 0 评论 -
矩形覆盖
剑指offer第10题: 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?理解:通过总结规律发现符合斐波那契数列,通过数列规则题的方法计算即可。public class Solution { public int RectCover(int target) { //...原创 2018-07-17 20:41:32 · 171 阅读 · 0 评论 -
二进制中1的个数
剑指offer第11题: 输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。理解:本题可以用最直接的方法,让1同最低位做与运算,如果结果不为0,说明这一位是1,计数器加1;另外一种方法是让输入n同(n-1)做与运算,这样每次运算可以消除一个“1”,同样可以计算“1”的个数。这种方法的效率更高,代码如下:public class Solution { ...原创 2018-07-23 09:20:13 · 199 阅读 · 0 评论 -
数值的整数次方
剑指offer第12题: 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。理解:因为equals不能用于基本变量类型,只能用于字符串等引用类型(“==”用于基本类型)。因此需要自己写一个equal方法,考虑到浮点类型丧失精确度有误差。再写一个用于常规指数运算的for循环power方法。另外要考虑底数、指数为0等...原创 2018-07-23 10:24:00 · 185 阅读 · 0 评论 -
调整数组顺序使奇数位于偶数前面
剑指offer第13题: 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。理解:算法的思路类似冒泡算法。如果后面的数字是奇数,前面的数字是偶数,就需要进行交换。内循环执行一轮就可以至少将一个数字交换到队首。外循环遍历整个数组。public class...原创 2018-07-23 11:22:11 · 191 阅读 · 0 评论 -
链表中倒数第k个结点
剑指offer第14题: 输入一个链表,输出该链表中倒数第k个结点。理解:想找到倒数第k个结点。用两个指针,先让一个指针走(k-1)步,然后两个指针再一起走。当先走的指针到达了末尾的时候,后走的slow指针指向的结点就是倒数第k个结点。/*public class ListNode { int val; ListNode next = null;...原创 2018-07-23 11:46:12 · 142 阅读 · 0 评论 -
翻转链表
剑指offer第15题: 输入一个链表,反转链表后,输出新链表的表头。理解:做循环,如果当前节点不为空的话,始终执行此循环,此循环的目的就是让当前节点从指向next到指向pre,如此就可以做到反转链表的效果。先用next保存head的下一个节点的信息,保证单链表不会因为失去head节点的原next节点而就此断裂。保存完next就可以让head指向pre了。/*pub...原创 2018-07-23 15:15:37 · 210 阅读 · 0 评论 -
合并两个排序链表
剑指offer第16题: 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。理解:首先考虑特殊情况的出现。常规情况中,对list1和list2中的val进行对比。根据对比的情况,赋予newList,让newList的next**指向Merge递归的结果**,这样才能连接成链。 对于链表的题一定要确认链表中间没有丢失,最后要确认是...原创 2018-07-23 16:28:12 · 161 阅读 · 0 评论 -
树的子结构
剑指offer第17题: 输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)理解:利用了递归的思想。在主方法里,先判断root2的根节点是否与root1相同,如果不同就需要判断是否与root1的left和right两个子结点相同。直到判断到有相同结点为止开始进入doesRoot1HaveRoot2方法。 当root2已经为null时,...原创 2018-07-23 17:51:31 · 179 阅读 · 0 评论 -
二叉树的镜像
剑指offer第18题: 操作给定的二叉树,将其变换为源二叉树的镜像。 输入描述: 二叉树的镜像定义:源二叉树 8 / \ 6 10 / \ / \ 5 7 9 11 镜像二叉树 ...原创 2018-07-23 20:47:39 · 207 阅读 · 0 评论 -
顺时针打印矩阵
剑指原创 2018-07-24 08:30:21 · 221 阅读 · 0 评论 -
包含min函数的栈
剑指offer第20题: 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。理解:定义两个栈,一个存放普通的压入值,另一个存放min值。压入时进行判断,如果出现更小的就压入stack2,弹出时如果最小的已经被弹出就将stack2中最小的pop掉。import java.util.Stack;public clas...原创 2018-07-24 08:31:31 · 182 阅读 · 0 评论 -
栈的压入、弹出序列
剑指offer第21题: 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)理解:本题的思路是按照轮次依次将push集合中的内...原创 2018-07-24 09:24:19 · 190 阅读 · 0 评论 -
从上往下打印二叉树
剑指offer第22题: 从上往下打印出二叉树的每个节点,同层节点从左至右打印。理解:本题是按层对二叉树进行打印的标准基础题。使用一个队列,或者ArrayList、LinkedList集合模拟一个队列,作为辅助空间。一边对已经压入的结点取出,提取值存入list,一边将取出的node的左右子结点压入。import java.util.ArrayList;impor...原创 2018-07-24 10:31:37 · 217 阅读 · 0 评论 -
二叉搜索树的后序遍历序列
剑指offer第23题: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。理解:首先应当理解后序遍历的特点,和搜索/排序二叉树的特点。后序遍历,根节点在最末尾;搜索二叉树,比根节点小的和比根节点大的分成两段排列在根节点之前。 首先通过循环找到后序遍历表中右子树的第一个结点,然后分类...原创 2018-07-24 14:26:42 · 252 阅读 · 0 评论 -
二叉树中和为某一值的路径
剑指offer第24题: 输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)理解:采用深度遍历的思想和递归的思想。首先将根结点的值减掉。然后判断是否满足了路径条件,如果不满足就需要对左子树和右子树分别递归。 需要注意的是,在...原创 2018-07-24 15:44:54 · 380 阅读 · 0 评论 -
复杂链表的复制
剑指offer第25题: 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)理解:本题是一个复制链表的题。看似比较复杂,其实原理还是非常简单的。一共有两类指针,一类是指向下一个,一类是指向任意一个。新建一个Rand...原创 2018-07-24 16:41:23 · 215 阅读 · 0 评论 -
二叉搜索树与双向链表
剑指offer第26题: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。理解:不能建立新的结点,只能改变指向,就是让left成为指向前一个的指针,right成为指向后一个的指针。由于是搜索二叉树,于是通过中序遍历+递归可以实现这个变化过程。 重要的是搞明白在互指的过程中pRoot和Head结点当前都指向的是...原创 2018-07-24 17:49:05 · 249 阅读 · 0 评论 -
字符串的排列
剑指offer第27题: 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。理解: 首先将字符串转换为字符数组进行处理,交换的形式如上图所示,进行递归处理,首先和自己进行交换,然后和第二个、第三个……,后面的进行递归交换,保证所有都交换一遍。交换完...原创 2018-07-24 23:52:23 · 309 阅读 · 0 评论 -
数组中出现次数超过一半的数字
剑指offer第28题: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。理解:想到了两种方法,第一种方法因为涉及了排序,复杂度较高。先进行排序,排序之后从前到后遍历,对相同数字进行计数,如果计没超过一半就换了其...原创 2018-07-25 00:39:34 · 325 阅读 · 0 评论 -
连续子数组的最大和
剑指offer第30题: HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个...原创 2018-07-25 10:09:41 · 338 阅读 · 0 评论 -
对称的二叉树
请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。理解:本题要利用递归的思想,这里的对称指的是镜面对称。 单独写一个递归方法,在主方法中进行调用。 要先通过两个if对终止条件进行处理,最后通过一个return巧妙递归,让左的左等于右的右、左的右等于右的左。/*public class TreeNode { ...原创 2018-05-08 11:31:45 · 241 阅读 · 0 评论 -
二叉树的下一个结点
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。理解:该题需要进行分类讨论。如果该结点有右子树,那么下一个结点就是右子树的最低左结点;如果没有那么就要看该结点是父结点的左还是右儿子,如果是左,那么下一个结点就是父结点;如果是右,那么下一个结点就要往上找父结点、父结点的父结点……在找的过程中,一...原创 2018-05-08 13:08:36 · 230 阅读 · 0 评论 -
按之字形顺序打印二叉树
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。理解:这道题和顺序按层打印思路是一模一样的,但是由于变成了蛇形打印,所以需要将暂存空间由队列/链表变成了栈,栈的FILO模式完美适合于蛇形打印的要求。 创建两个栈,轮流扮演输出空间和暂存空间,分别负责奇数层和偶数层的输出。通过leve...原创 2018-05-08 11:05:18 · 209 阅读 · 0 评论 -
把二叉树打印成多行
从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。理解:本题的重点是要想到使用暂存空间,按行打印当前行时就要将下一行要打印的内容存放到暂存空间中,这样才能保证按行打印且不丢失树的关联性。根据题目要求的不同,是均为从左至右打印还是蛇形打印,来选择暂存空间的类型,是栈还是队列、链表。import java.util.ArrayList;import java.u...原创 2018-05-08 10:46:58 · 299 阅读 · 0 评论 -
序列化二叉树
请实现两个函数,分别用来序列化和反序列化二叉树。理解:序列化二叉树就是要按照一个固定的序列模式对结点进行排序,反序列化只要按照同样的规则复原即可。 这里采用前序遍历的方式,创建一个StringBuffer()对象方便改变字符串内容,按照父结点-&gt;左-&gt;右的顺序依次序列化,其中子结点均为递归调用。 需要注意的是:一定要对null结点进行同样的序列化标记,这样才能正...原创 2018-05-07 14:23:26 · 208 阅读 · 0 评论 -
二叉搜索树的第k个结点
给定一颗二叉搜索树,请找出其中的第k大的结点。例如, 5 / \ 3 7 /\ /\ 2 4 6 8 中,按结点数值大小顺序第三个结点的值为4。理解:想要找出第k大的结点,能够对二叉树的结点val进行排序是最好不过,并且辅助很多类似问题的解答。 对二叉搜索树进行中序遍历后的顺序正是从小到大的排序,所以思路很清楚:首先进行中序遍历,然后根据需要提取出第k个结点。 注意将中序遍历写...原创 2018-05-07 11:10:56 · 214 阅读 · 0 评论 -
数据流中的中位数
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。理解:数据流中找中位数,就会涉及到数据的插入和从现有数据中查找当前中位数这两个过程,如果需要控制复杂度,就需要综合考虑插入和查找两种操作的复杂度。 如果是无序数组插入容易但查找难,如果是有序数...原创 2018-05-06 21:50:47 · 249 阅读 · 0 评论 -
滑动窗口的最大值
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1...原创 2018-05-06 21:14:50 · 207 阅读 · 0 评论 -
矩阵中的路径
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如 a b c e s f c s a d e e 矩阵中包含一条字符串”bcced”的路径,但是矩阵中不包含”abcb”路径,因为字符串的第一个字符b占据了矩...原创 2018-05-06 16:36:37 · 269 阅读 · 0 评论 -
机器人的运动范围
地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?理解:此题拿到手首先是一个棋牌扫描的...原创 2018-05-06 15:22:47 · 199 阅读 · 0 评论