![](https://img-blog.csdnimg.cn/20201014180756913.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
剑指offer
但觉
没有人会漫无目的地旅行,那些迷路者是希望迷路。
展开
-
剑指offer-面试题4 - 替换空格
题目描述:请实现一个函数,把字符串中的每个空格替换成”%20”。题目解析:一个空格换成%20后长度增加2,所以先统计出字符串中一共有多少个空格,假如是n个空格,那么在替换后,字符串的长度增加了2n个字符。所以从后开始遍历字符数组,遇到空格,就替换成%20。//替换空格 public static char[] replace(char[] array) { if (array原创 2017-01-17 14:34:16 · 274 阅读 · 0 评论 -
剑指offer-面试题24-二叉搜索树的后序遍历序列
题目描述:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回true。否则返回false。假设输入的数组的任意两个数字都互不相同。题目分析:在后序遍历得到的序列中,最后一个数值是树的根节点的值。在数组中的数字可以分为两部分,第一部分是左子树的结点的值,它们都比根值要小,第二部分是右子树的结点的值,它们都比根值要大。比如5,7,6,9,11,10,8.8是根节点,那么5,7,原创 2017-01-19 16:18:45 · 206 阅读 · 0 评论 -
剑指offer-面试题25-二叉树中和为某一值的路径
题目描述:输入一棵二叉树和一个整数, 打印出二叉树中结点值的和为输入整数的所有路径。从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。题目分析:由于路径是从根节点出发到叶子结点,也就是说路径总是以根结点为起点,因此我们首先需要遍历根节点。在树的前序遍历后序遍历和中序遍历中只有前序遍历是先访问根节点的。当前序遍历访问到某一结点时,我们把该结点添加到路径上,并累加该结点的值,如果该结点为叶子结点原创 2017-01-19 18:52:44 · 244 阅读 · 0 评论 -
剑指offer-面试题26-复杂链表的复制
题目描述:请实现函数ComplexListNode clone(ComplexListNode head),复制一个复杂链表。在复杂链表中,每个结点除了有一个next 域指向下一个结点外,还有一个sibling 指向链表中的任意结点或者null。题目解析: 如图结构。 第一步,根据原始链表的每一个结点N创建对应的N’,我们把N’接在N的后面。处理后如图 第二步,假如B指向E,那么B’指向E原创 2017-01-19 19:30:09 · 290 阅读 · 0 评论 -
剑指offer-面试题27-二叉搜索树与双向链表
题目描述:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。题目分析:在搜索二叉树中,左子结点的值总是小于父结点的值,右子结点的值总是大于父结点的值。因此我们在转换成排序双向链表时,原先指向左子结点的指针调整为链表中指向前一个结点的指针,原先指向右子结点的指针调整为链表中指向后一个结点指针。接下来我们考虑该如何转换。中序遍历二叉搜索树后原创 2017-01-19 21:06:22 · 433 阅读 · 0 评论 -
剑指offer-面试题28-字符串的排列
题目描述:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c 所能排列出来的所有字符串abc,acb,bac ,bca,cab 和cba 。题目分析:可以分成两步。第一步求所有可能出现在第一个位置的字符,即把第一个字符和后面所有的字符交换。第二步固定第一个字符,求后面所有字符的排列。这时候再把后面的字符分成两部分,后面字符的第一个字符以及这个字符之后的所有原创 2017-01-19 21:24:50 · 219 阅读 · 0 评论 -
剑指offer-面试题29-数组中出现次数超过一半的数字
题目描述:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9 的数组{ 1, 2, 3, 2, 2, 2, 5, 4, 2}。由于数字2在数组中出现了5 次,超过数组长度的一半,因此输出2 。题目分析:方法一:基于Partition函数的O(n)算法。数组中有一个数字出现的次数超过数组长度的一半,那么排序后,要求的数肯定是中位数。所以可以利用快排的Partition函原创 2017-01-19 21:52:58 · 429 阅读 · 0 评论 -
剑指offer-面试题30-最小的k个数
题目描述:输入n个整数,找出其中最小的k个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4.题目分析:这道题最简单的思路莫过于把n个整数排序,然后最前面的k个数就是最小的k个数,但是时间复杂度是O(nlogn)。我们应该想一想有没有更快的方法。解法一:O(n)的算法,只有当可以修改输入的数组时可用。 基于快排里的Partition函数,基于数组中的第k个数来调原创 2017-01-20 15:59:53 · 251 阅读 · 0 评论 -
剑指offer-面试题31-连续子数组的最大和
题目描述:输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。题目分析:用动态规划实现。如果用函数f(i)表示以第i个数字结尾的子数组的最大和,那么我们需要求出max[f(i)],其中i大于等于0小于n。 这个公式的意义是,当以第i-1个数字结尾的子数组中所有数字的和小于0时,如果把这个负数和第i个数累加,得到的结果原创 2017-01-20 21:02:53 · 264 阅读 · 0 评论 -
剑指offer-面试题33-把数组排成最小的数
题目描述:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字321323。题目分析:两个数字m 和n能拼接成数字mn和nm。如果mn < nm,那么我们应该打印出m,也就是m 应该排在n 的前面,我们定义此时m 小于n:反之,如果nm < mn,我们定义n小于m。如果mn=nm,m 等于n。原创 2017-01-22 15:40:23 · 249 阅读 · 0 评论 -
剑指offer-面试题34-丑数
题目描述:我们把只包含因子2,3和5的数称作丑数。求按从小到大的顺序的第1500个丑数。例如6,8都是丑数,14不是,因为它包含因子7.习惯上我们把1当做第一个丑数。题目分析:1)暴力解法。逐个判断每个整数是不是丑数//判断是否丑数 public static boolean isUglyNum(int number) { while (number % 2 == 0) {原创 2017-01-22 16:19:19 · 293 阅读 · 0 评论 -
剑指offer-面试题35-第一个只出现一次的字符
题目描述:在字符串中找出第一个只出现一次的字符。比如输入abaccdeff,则输出b。题目分析:用哈希表来实现,key,value对,key是字符,value是出现的次数,循环第一遍,统计每个字符出现的次数,循环第二遍,找出第一个只出现一次的字符。//找出第一个只出现一次的字符 public static char findOneCharacter(char[] array) {原创 2017-01-22 17:08:13 · 286 阅读 · 0 评论 -
剑指offer-面试题36-数组中的逆序对
题目描述:在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。例如在数组{7, 5, 6, 4 中, 一共存在5 个逆序对,分别是(7, 6)、(7,5),(7, 4)、(6, 4)和(5, 4)。题目分析:原创 2017-01-23 10:25:03 · 283 阅读 · 0 评论 -
剑指offer-面试题37-两个链表的第一个公共结点
题目描述:输入两个链表,找出它们的第一个公共结点。题目分析:两个链表,当找到第一个相同的结点后,其后的所有结点都是相同的,是Y型。如果两个链表有公共结点,那么公共结点出现在两个链表的尾部。如果我们从两个链表的尾部开始往前比较,最后一个相同的结点就是我们要找的结点。在上述思路中,我们需要用两个辅助钱。如果链表的长度分别为m 和n,那么空间复杂度是O(m+n)。这种思路的时间复杂度也是O(m+n)。还有原创 2017-01-23 15:30:55 · 260 阅读 · 0 评论 -
剑指offer-面试题38-数字在排序数组中出现的次数
题目描述:统计一个数字在排序数组中出现的次数。例如输入排序数组{ 1, 2, 3, 3, 3, 3, 4, 5}和数字3 ,由于3 在这个数组中出现了4 次,因此输出4 。题目分析:利用改进的二分算法。 如何用二分查找算法在数组中找到第一个k,二分查找算法总是先拿数组中间的数字和k作比较。如果中间的数字比k大,那么k只有可能出现在数组的前半段,下一轮我们只在数组的前半段查找就可以了。如果中间的数字比原创 2017-01-24 14:35:07 · 364 阅读 · 0 评论 -
剑指Offer-面试题39-二叉树的深度
题目描述:输入一棵二叉树的根结点,求该树的深度。从根结点到叶子点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。题目分析:如果一棵树只有一个结点,它的深度为1。 如果根结点只有左子树而没有右子树, 那么树的深度应该是其左子树的深度加1,同样如果根结点只有右子树而没有左子树,那么树的深度应该是其右子树的深度加1. 如果既有右子树又有左子树, 那该树的深度就是其左、右子树深度的原创 2017-01-24 14:57:02 · 383 阅读 · 0 评论 -
剑指offer-面试题40-数组中只出现一次的数字
题目描述:一个整型数组里除了两个数字之外,其他的数字都出现了两次,请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。题目分析:例如输入数组{2, 4, 3, 6, 3, 2, 5,5 },因为只有4 、6 这两个数字只出现一次,其他数字都出现了两次,所以输出4和6 。我们想到异或运算的一个性质:任何一个数字异或它自己都等于0。也就是说, 如果我们从头到尾依次异或数组原创 2017-01-24 15:32:25 · 299 阅读 · 0 评论 -
剑指Offer-面试题41-和为s 的两个数字vs 和为s 的连续正数序列
题目描述:输入一个递增排序的数组和一个数字s,在数组中查找两个数,得它们的和正好是s。如果有多对数字的和等于s,输出任意一对即可。例如输入数组{1 、2 、4、7 、11 、15 }和数字15. 由于4+ 11 = 15 ,因此输出4 和11 。题目分析:我们先在数组中选择两个数字,如果它们的和等于输入的s,我们就找到了要找的两个数字。如果和小于s 呢?我们希望两个数字的和再大一点。由于数组已经排好原创 2017-01-24 16:50:04 · 327 阅读 · 0 评论 -
剑指offer-面试题23-从上往下打印二叉树
题目描述:从上往下打印出二叉树的每个结点,同一层的结点按照从左向右的顺序打印。、题目分析:可以使用队列,先把根结点放入到队列中,然后取出头结点,将其左孩子和右孩子放入到队列中,队列是先进先出的特性,然后再从队列中取数据,以此类推//从上往下打印二叉树 public static void printTreeFromTopToBottom(BinaryTreeNode root) {原创 2017-01-19 15:22:24 · 217 阅读 · 0 评论 -
剑指offer-面试题22-栈的压入、弹出序列
题目描述:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压栈序列,序列4,5,3,2,1是该栈的一个弹出序列,4,3,5,1,2则不可能是弹出序列。题目分析:可以借助辅助栈,通过一个一个向栈中加入压栈序列中的元素,每次压入都跟出栈序列中元素作比较,如果相等,则弹出,同时出栈序列下标后移。//栈的压入原创 2017-01-19 15:06:55 · 274 阅读 · 0 评论 -
剑指offer-面试题21-包含min函数的栈
题目描述:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小素的min 函数。在该栈中,调用min、push 及pop的时间复杂度都是0(1)。题目分析:借助一个辅助栈,当向栈中压入元素时,跟辅助栈顶元素作比较,把最小的放到辅助栈中。每次都把最小元素放入辅助栈,这样在弹出最小元素后,剩下的栈中栈顶依然是最小元素。//包含min函数的栈 public static class StackM原创 2017-01-19 14:35:00 · 212 阅读 · 0 评论 -
剑指offer-面试题3 二维数组中的查找
目前研三,毕业在即,之前做Android开发,现在想转到后台开发,却发现算法部分太过欠缺,所以就去博客上看别人写的剑指offer题的见解。声明,我这里只是针对别人写的,自己敲一遍代码,然后发表出来,算是自己的日记,方便日后复习浏览。并无他意。二维数组中的查找题目描述:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的原创 2017-01-17 13:49:15 · 549 阅读 · 0 评论 -
剑指offer-面试题5-从尾到头打印列表
题目描述:输入个链表的头结点,从尾到头反过来打印出每个结点的值。题目解析:有链表,有头结点,按照链表的头结点开始遍历,只能是从前往后,但是栈是先进后出,所以可以使用栈,当然也可以使用递归方式。我这里代码使用的是栈。//给出链表头结点,从尾到头输出链表 public static class ListNode {//结点对象 int data; ListNode原创 2017-01-17 14:49:30 · 216 阅读 · 0 评论 -
剑指offer-面试题6-重建二叉树
题目描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。题目分析:给出前序遍历和中序遍历可以构建出二叉树,给出中序遍历和后序遍历可以构建出二叉树,但是给出前序遍历和后序遍历却不能构建出二叉树,比如前序遍历ABC,后序遍历CBA,那么就不能构建出唯一的二叉树。前序遍历可以确定出根节点的位置,中序遍历可以根据根节点找到根节点左侧是左子树的原创 2017-01-17 16:33:13 · 237 阅读 · 0 评论 -
剑指offer-面试题7-用两个栈实现队列
题目描述:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail 和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能。题目分析:栈是后进先出,队列是先进先出,所以可以考虑一个栈用来删除,一个栈用来添加元素。//用两个栈实现队列 public static class StackQueue<T>{ private Stack<T>原创 2017-01-17 16:57:22 · 249 阅读 · 0 评论 -
剑指offer-面试题8-旋转数组的最小数字
题目描述:一个递增排序的数组,把数组中最开始的若干个元素放到数组的末尾,称之为数组的旋转,输出旋转数组的最小元素。比如,1,2,3,4,5翻转后4,5,1,2,3。找出旋转数组中最小的数字题目解析://翻转数组 public static int getMinNum(int[] numbers) { if (numbers == null || numbers.length原创 2017-01-17 19:04:59 · 153 阅读 · 0 评论 -
剑指offer-面试题9-菲波那切数列
题目描述:菲波那切数列;定义:F0=0,F1=1,Fn=Fn-1+Fn-2(n>=2,n∈N*)。题目分析:采用递归来实现会出现重复计算的情况,这里采用动态规划思想,保存中间运算结果,避免不必要的计算。有个上楼梯的问题跟这个很像。上楼梯,一次可以选择上一个台阶或者上两个台阶,当上到第100个台阶的时候有多少种上法。//菲波那切数列 public static int getFib(int n原创 2017-01-17 19:15:49 · 249 阅读 · 0 评论 -
剑指offer-面试题10-二进制中1的个数
题目描述:实现一个函数,输入一个整数,输出该数二进制表示中1的个数。题目分析:把一个整数减去1,再和原整数做与运算,会把最右边一个1变成0,那么一个整数的二进制表示中有多少个1,就可以进行多少次这样的操作。比如101减1后是100,100&101=100,然后100-1=011,011&100=000.所以一共进行了两次与操作。就有两个1. //求一个整数二进制表示中1的个数 public原创 2017-01-17 19:27:51 · 165 阅读 · 0 评论 -
剑指offer-面试题12-打印1到最大的n位数
题目描述:输入数字n,按顺序打印出从1到最大的n位十进制数。比如输入3,打印1,2,3一直到最大的三位数999题目分析:这个题不是简单的用一个for循环,当n很大的时候,就会超过数值的最大值界面,导致溢出。所以考虑使用字符串表示整数。//输出n位数 public static void printNDigits(int n) { if (n < 1) {原创 2017-01-19 08:56:36 · 268 阅读 · 0 评论 -
剑指offer-面试题11-数值的整数次方
题目描述:实现函数double power(double base, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。题目解析:这个题使用for循环可以完成,但是可以考虑使用递归。假如exponent是偶数,那么除以2,如果是奇数,则减一再除2.//数值的整数次方 public static double power(int base,原创 2017-01-17 19:38:30 · 244 阅读 · 0 评论 -
剑指offer-面试题13-在O(1)时间删除链表结点
题目描述:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。题目解析:如果从头到尾遍历找到要删除的节点的前一个节点,将前一个节点的next指针指向删除节点的next,那么时间复杂度是O(n)。所以不能这样做。如果采取是将删除节点的下一个节点的值复制到要删除的节点,然后再将下一个节点删除,那么时间复杂度就是O(1)。如果要删除的节点是最后一个节点,那么我们还是需要遍历链表。所以原创 2017-01-19 09:26:06 · 308 阅读 · 0 评论 -
剑指offer-面试题14-调整数组顺序使奇数位于偶数前面
题目描述:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位予数组的后半部分。题目解析:维护两个下标first和end,first初始指向数组首位置,end初始指向数组末位置,first只能向后走,end只能向前走,比较first和end指向的数据,如果first指向的是偶数,end指向的是奇数,则互换数据。直到两个下标相遇。//将一个数组中奇数放到前原创 2017-01-19 09:48:51 · 234 阅读 · 0 评论 -
剑指offer-面试题15-链表中倒数第k个结点
题目描述:输入一个链表,输出该链表中倒数第k 个结点.为了符合大多数人的习惯,本题从1 开始计数,即链表的尾结点是倒数第1 个结点.例如一个链表有6 个结点,从头结点开始它们的值依次是1 、2、3、4、5 、6。这个个链表的倒数第3 个结点是值为4 的结点。题目分析:使用两个指针,第一个指针先走k-1步,到达第k个结点,然后第二个指针再开始走,这样,两个指针之间隔了k-1步,当第一个指针走到尾的时候原创 2017-01-19 10:23:01 · 143 阅读 · 0 评论 -
剑指offer-面试题16-反转链表
题目描述:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。题目分析:直接一遍遍历下来,使用尾插法,记录前一个结点//反转链表 public static ListNode reverseList(ListNode head) { ListNode reverseListHead = null;//反转后的头结点 ListNode cur原创 2017-01-19 10:53:29 · 233 阅读 · 0 评论 -
剑指offer-面试题17-合并两个排序的链表
题目描述:输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。例如链表1,3,5,7和链表2,4,6,8.合并后链表为1,2,3,4,5,6,7,8题目解析:先是判断给出的两个链表是否是空表。然后再比较两个表的头结点,小的结点作为头结点,然后两个链表依次遍历,同时比较大小,作为头结点的下一个结点。书中给的是使用递归,但是递归会耗费栈内存。所以直接用循环遍历就好。//合并链表原创 2017-01-19 11:11:06 · 361 阅读 · 0 评论 -
剑指offer-面试题18-树的子结构
题目描述:输入两棵二叉树A 和B,判断B 是不是A 的子结构。题目分析:先寻找跟子树根结点相等的结点,找到后再去比较其左右子树是否相等//查找是否树的的子结构 public static boolean matchBinaryTree(BinaryTreeNode tree1, BinaryTreeNode tree2) { if (tree2 == null) {//树2的原创 2017-01-19 11:32:04 · 241 阅读 · 0 评论 -
剑指offer-面试题19-二叉树的镜像
题目描述:请完成一个函数,输入一个二叉树,该函数输出它的镜像。题目分析:就是以根结点为中轴线,反转,像照镜子一样。 // 二叉树的镜像 public static void mirrorTree(BinaryTreeNode root) { if (root != null) { BinaryTreeNode temp = root.left;原创 2017-01-19 11:46:18 · 202 阅读 · 0 评论 -
剑指offer-面试题20-顺时针打印矩阵
题目描述:输入一个矩阵,按照从外向里以顺时针的顺序依次扫印出每一个数字。题目解析:主要是对行号和列号的控制//顺时针打印矩阵 public static void printMatrix(int[][] arr) { if (arr == null) { return; } int x = 0, y = 0;//行x列y原创 2017-01-19 14:04:01 · 257 阅读 · 0 评论 -
剑指offer-面试题42-翻转单词顺序VS左旋转字符串
题目一描述:输入一个英文句子,翻转句子中单词的顺序,但单词内字啊的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串”I am a student. ”,则输出”student. a am I”。题目一分析:第一步翻转句子中所有的字符。比如翻转“I am a student. ”中所有的字符得到”.tneduts a m a I”,此时不但翻转了句子中单词的顺序,连单词内的字符顺序也被原创 2017-01-26 10:22:54 · 227 阅读 · 0 评论