剑指offer
文章平均质量分 53
总结的剑指offer的66道面试题,代码全部用java语言编写。
zhumqs
这个作者很懒,什么都没留下…
展开
-
20. 顺时针打印矩阵
题目描述 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数 字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.思路 1.分析发现,我们可以通过循环的每一次打印矩阵中的一...原创 2018-09-07 14:41:41 · 158 阅读 · 0 评论 -
23. 二叉搜索树的后序遍历序列
思路抓住二叉搜索树的特点,对于后序遍历序列,其每个子树的最后一个元素会比前面的左边一部分大,右边一部分小,这样便可以通过递归来判断AC代码package com.zhumq.leetcode;import java.util.Arrays;import org.junit.Test;public class IsBehSequenceBST { public ...原创 2018-09-10 20:47:25 · 124 阅读 · 0 评论 -
24. 二叉树中和为某值的路径
思路这题是从LeetCode上Path Sum I和PathII演变过来的,只不过这题需要返回所有满足要求的节点序列,难度稍有增加。主要思路相同:找出路径之和为指定整数的路径,就需要遍历二叉树的所有路径。此外,由于路径是指根结点到叶子结点的线段,因此采用深度优先的方式遍历二叉树。深度优先算法又分为:先序遍历、中序遍历、后序遍历,其中先序遍历符合我们的要求。首先需要创建一个栈,用来保...原创 2018-09-10 20:49:32 · 178 阅读 · 0 评论 -
26. 二叉搜索树转换成双向链表
思路比如如下图中的二叉搜索树,则输出转换之后的排序双向链表为: 在二叉树中,每个结点都有两个指向子节点的指针。在双向链表中,每个结点也有两个指针,他们分别指向前一个结点和后一个结点。由于这两种结点的结构相似,同时二叉搜索树也是一种排序的数据结构,因此在理论上有可能实现二叉搜索树和排序的双向链表的转换。在搜索二叉树中,左子结点的值总是小于父节点的值,右子节点的值总是大于父节点的值。...原创 2018-09-10 20:50:23 · 157 阅读 · 0 评论 -
27. 字符串全排序
思路1直接使用求解全排序问题的next_permutation() 函数,next_permutation() 的具体实现见Next Permutationpackage com.zhumq.leetcode;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import o...原创 2018-09-10 20:52:03 · 161 阅读 · 0 评论 -
数组中出现次数超过一半的数字
思路1基于Partition函数的O(n)算法,受快速排序的算法的启发,在随机快速排序的算法中,我们先在数组中随机的选择一个数字,然后调数组中数字的顺序,使得比选中的数字小数字排在它的左边,比选中的数字大的数字都排在它的右边。比如这个选中的数字的下标刚好是n/2,那么这个数字就是数组中的中位数。如果它的下标大于n/2,那么中位数应该位于它的左边,我们可以接着在它的左边部分的数组中查找。...原创 2018-09-10 20:52:46 · 111 阅读 · 0 评论 -
连续子数组最大和
LeetCode的Maximum SubArray问题,主要有三种解法。思路1分治法Divide and Conquer Approach来解,这个分治法的思想就类似于二分搜索法,我们需要把数组一分为二,分别找出左边和右边的最大子数组之和,然后还要从中间开始向左右分别扫描,求出的最大值分别和左右两边得出的最大值相比较取最大的那一个,代码如下:/* * 分治法的思想就类...原创 2018-09-10 20:53:24 · 139 阅读 · 0 评论 -
整数区间中1出现的次数
思路1最简单的方法,分别求从1到n之间每个数中的1的个数,由于整数n的位数为O(logn),我们要判断一个数有多少个1,需要判断其每一位是否为1,这样一个数就需要判断O(logn)次,而总共有n个数需要求,那么该方法的时间复杂度为O(nlogn)。/* * 累加1到n中每个整数1出现的次数。 * 每次通过对10求余数判断当前位是不是1. ...原创 2018-09-10 20:54:14 · 416 阅读 · 0 评论 -
丑数
思路1逐个判断每个整数是不是丑数的解法,直观但不够高效。所谓一个数m是另一个数n的因子,是指n能被m整除,也就是说n%m==0.根据丑数的定义,丑数只能被2,3,5整除。也就是说如果一个数能被2整除,我们把它连续除以2;如果能被3整除,就连续除以3;如果能被5整除,就除以5.如果最后我们得到的是1,那么这个数就是丑数,否则不是。接下来,我们只需要按照顺序判断每个整数是不是丑数,...原创 2018-09-10 20:54:49 · 118 阅读 · 0 评论 -
数组中的逆序对
思路1最简单的方法是顺序数组,将每个数字与后面的比较,统计逆序对的个数,这种方法的时间复杂度为O(n*n),这种方法会超时。这里可以巧妙利用归并排序的思想,只需在归并排序的基础上稍作修改即可!我们以数组{10,5,6,8,4,7,9}为例来分析统计逆序对的过程,每次扫描到一个数字的时候,我们不能拿它和后面的每一个数字做比较,否则时间复杂度就是O(n*n)因此我们可以考虑先比较两个相邻的...原创 2018-09-10 20:55:49 · 160 阅读 · 0 评论 -
数组中第k小的元素
思路1O(n)的算法,只有当我们可以修改输入的数组时可用从上一题中我们可以得到启发,我们同样可以基于Partition函数来解决这个问题。如果基于数组的第k个数字来调整,使得比第k个数字小的所有数字都位于数组的左边,比第k个数字大的所有数字都位于数组的右边。这样调整之后,位于数组中左边的k个数字就是最小的k个数字。 /* 解法1: * 使用快排的parti...原创 2018-09-10 20:56:29 · 902 阅读 · 0 评论 -
二叉树的深度
递归思路例如,如下图的二叉树的深度为4,因为它从根节点到叶结点的最长的路径包含4个结点(从根结点1开始,经过2和结点5,最终到达叶结点7)我们可以从另一种角度来理解树的深度。如果一棵树只有一个结点,它的深度为1,如果根节点只有左子树而没有右子树,那么树的深度应该是其左子树的深度+1.同样如果根节点只有右子树而没有左子树,那么树的深度应该是其右子树+1.如果既有左子树又有右子树,那概...原创 2018-09-11 10:24:01 · 162 阅读 · 0 评论 -
数组中只出现1次的两个数
思路首先我们可以考虑下这个题目的简化版——数组中除一个数字只出现1次外,其它数字都成对出现,要求尽快找出这个数字。根据异或运算的特点,直接异或一次就可以找出这个数字。现在数组中有两个数字只出现1次,直接异或一次只能得到这两个数字的异或结果,但光从这个结果肯定无法得到这个两个数字。因此我们来分析下简化版中“异或”解法的关键点,这个关键点也相当明显——数组只能有一个数字出现1次。设题目...原创 2018-09-11 11:29:19 · 215 阅读 · 0 评论 -
数组中和为定值的两个数字
题目:输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对的和等于s,则输出全部对。思路例如输入数组{1,2,4,7,11,15}和数字15.由于4+11=15,因此输出4和11.最简单肯定是O(n*n)的方法,也就是先在数组中固定一个数字,再依次判断数组中其余n-1个数字与它的和是不是等于s。时间复杂度太高,效率太低。接着我们寻找更好的算法...原创 2018-09-11 11:30:17 · 556 阅读 · 0 评论 -
和为定值的连续正数序列
思路有了数组中和为定值的两个数字的经验,我们也考虑用两个数small和big分别表示序列的最小值和最大值。首先把small初始化为1,big初始化为2.如果从small到big的序列的和大于s,我们可以从序列中去掉较小的值,也就是增大small的值。如果从small到big的序列的和小于s,我们可以增大big,让这个序列包含更多的数字。因为这个序列至少要有两个数字,我们一直增加small ...原创 2018-09-11 11:31:03 · 198 阅读 · 0 评论 -
两个链表的公共节点
思路1使用栈 从链表结点的定义可以看出,这两个链表是单链表。如果两个单向链表有公共的结点,那么这两个链表从某一结点开始,它们的m_pNext都指向同一个结点,但由于是单向链表的结点,之后他们所有结点都是重合的,不可能再出现分叉。所以两个有公共结点而部分重合的链表,拓扑形状开起来像一个Y,而不可能项X。 如果两个链表有公共结点,那么公共结点出现在两个链表的尾部。如果我们从两个链表...原创 2018-09-11 11:31:37 · 2942 阅读 · 1 评论 -
数字在排序数组中出现的次数
思路1这道题让我们在一个有序整数数组中寻找相同目标值的起始和结束位置,而且限定了时间复杂度为O(logn),这是典型的二分查找法的时间复杂度,所以这道题我们也需要用此方法,我们的思路是首先对原数组使用二分查找法,找出其中一个目标值的位置,然后向两边搜索找出起始和结束的位置,代码如下: //先找到一个目标值的位置,再左右搜索找到起始位置 public int[] s...原创 2018-09-11 11:32:05 · 153 阅读 · 0 评论 -
左旋转字符串
思路以”abcdeftg”为例,我们可以把它分为两个部分,由于想把它的前两个字符一道后面,我们就把前面两个字符分到第一部分,把后面的所有字符都分到第二个部分。我们先反转这两部分,于是就得到了“bagfedc",接下来我们再翻转整个字符串,得到了”cdefgab"刚好就是把原始字符串左旋转2位的结果。 public class LeftRotateString { /...原创 2018-09-11 11:32:34 · 291 阅读 · 0 评论 -
反转单词顺序
思路1递归思想思路2利用栈思路3先根据空格将字符串转成字符串数组,然后倒序拼接。思路4反转整个句子,然后反转每个单词。思路5反转每个单词,然后反转这个句子。...原创 2018-09-11 11:33:04 · 354 阅读 · 0 评论 -
扑克牌的顺序
思路判断5个数字是不是连续的,最直观的方法是把数组排序。值得注意的是,由于0可以当成任意的数字,我们可以用0去补满数组中的空缺。如果排序之后的数组不是连续的,即相邻的两个数字像个若干个数字,但只要我们有足够的0可以补满这两个空缺的数字,这个数组实际上还是连续的。举个例子,数组排序之后为{0,1,3,4,5},在1和3之间空缺一个2,刚好我们有一个0,也就是我们可以把它当成2去填补这个空缺。...原创 2018-09-11 19:55:14 · 2157 阅读 · 1 评论 -
约瑟夫环问题
思路1:链表模拟普通解法,用链表的方法去模拟这个过程,N个人看作是N个链表节点,节点1指向节点2,节点2指向节点3,……,节点N-1指向节点N,节点N指向节点1,这样就形成了一个环。然后从节点1开始1、2、3……往下报数,每报到M,就把那个节点从环上删除。下一个节点接着从1开始报数。最终链表仅剩一个节点。它就是最终的胜利者。 缺点: 要模拟整个游戏过程,时间复杂度高达O(nm...原创 2018-09-12 10:10:41 · 993 阅读 · 0 评论 -
不用加减乘除做加法
思路首先我们分析人们是如何进行十进制的加法的,比如是如何得出5+17=22的结果的?实际上可以分三步进行:第一步只做各位相加不进位,此时相加的结果是12,第二步做进位,5+7中有进位,进位的值为10;第三步,把前面的两个结果加起来12+10的结果是22,刚好5+17=22。求两个数之和,四则运算都不能用还能用什么?对数字做运算,除了四则运算之外,也就只剩下位运算了。位运算是针对...原创 2018-09-12 20:17:29 · 157 阅读 · 0 评论 -
无聊的1+2+...+n
思路1这些关键字都不能用,那么只能用递归去模拟循环,逻辑表达式的短路原则去模拟判断了。 //用递归替代循环,用&&的短路来替代条件判断 public int sum(int n) { int result = n; /* * 递归跳出条件,当n>0时,需要判断后续的条件所以会递到sum(n-1)!...原创 2018-09-12 20:24:50 · 183 阅读 · 0 评论 -
字符串转换成数字
关于这道题目,题目本身还是不错的,真正核心的代码也就那么两行,大部分代码基本都在做非法输入的检查。具体代码如下:package com.zhumq.leetcode;import java.util.Scanner;import org.junit.Test;public class StringToInteger { public Integer stringToI...原创 2018-09-14 19:30:22 · 529 阅读 · 0 评论 -
数组中重复的数字
题目在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。思路使用HashSet,在存放时判断每个元素是否已经存在,存在则直接返回这个元素即可。package com.zh...原创 2018-09-14 19:30:46 · 173 阅读 · 0 评论 -
构建乘积数组
题目给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。不能使用除法。思路由于不能使用除法,故只能通过累积来计算,一个很直观的方法就是开两个数组,一个从左开始累积,一个从右开始累积,最后对应位置的元素乘起来就行了。但是仔细想想,会发现从右开始累积的...原创 2018-09-14 19:34:11 · 117 阅读 · 0 评论 -
正则表达式匹配
题目请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而’*’表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配。思路1*表示之前那个字符可以有0个,1个或是多个,就是说,字符串a*b,可以表示b...原创 2018-09-14 19:40:19 · 204 阅读 · 0 评论 -
表示数值的字符串
具体代码如下:package com.zhumq.leetcode;import java.util.Scanner;import org.junit.Test;public class StringIsNumeric { /** * 解法1:根据字符串中每个字符进行判断分析 */ public boolean stringIsNumeric...原创 2018-09-15 19:52:24 · 124 阅读 · 0 评论 -
字符流中第一个不重复的字符
AC代码package com.zhumq.leetcode;import java.util.HashSet;import java.util.LinkedHashMap;import java.util.Map;import java.util.Scanner;import java.util.Set;import org.junit.Test;public cl...原创 2018-09-15 20:24:34 · 154 阅读 · 0 评论 -
链表中环的入口结点
题目一个链表中包含环,请找出该链表的环的入口结点。思路1利用HashSet元素不能重复,将链表从头开始依次添加到HashSet中,并判断每次添加是否成功,显然第二次到达环的入口时添加会失败,直接返回当前节点即可。 /** * 解法1:使用HashSet元素不能重复做 */ public ListNode entryNodeOfLinke...原创 2018-09-16 15:54:52 · 191 阅读 · 0 评论 -
删除链表中重复的结点
题目在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为1->2->5。思路1递归做法,从链表头开始往后找与这个结点相同的最后一个结点,如果这一段的长度为1那么保留下来;如果长度大于1,那么这段要删掉,后面的链表就递归处理。 ...原创 2018-09-16 16:29:58 · 159 阅读 · 0 评论 -
二叉树中序遍历的下一个结点
题目给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。思路来分析一下,中序遍历,先访问左子树,然后是根,最后是右子树;也就是说,当前结点有没有左子树对该问题没有影响,因为,中序遍历的下一个结点一定不可能在左子树中,所以我们主要关注当前结点有没有右子树。1)当前结点有右子树,那么下一个结点一定在右...原创 2018-09-16 17:04:49 · 248 阅读 · 0 评论 -
对称的二叉树
题目请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。思路递归的思路来做。package com.zhumq.leetcode;public class IsSymmetric { public class TreeNode { int val = 0; TreeNode le...原创 2018-09-17 15:53:05 · 152 阅读 · 0 评论 -
把二叉树打印成多行
题目从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。思路1层序遍历,只有一点需要考虑,就是如何把层序遍历序列按层分开来,因为返回的是每一层的遍历序列。最简单的做法是遍历当前层的时候就逐步确定下一层最右边的结点(遍历的过程中,下一层的最右结点一直在更新),这样当这一层遍历完时,下一层的最右结点也就确定了,这样当遍历下一层的时候就有了一个终点,这样子就完成了分层。...原创 2018-09-17 16:03:31 · 197 阅读 · 0 评论 -
按之字形顺序打印二叉树
题目请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。思路思路主要就是如何把层序遍历序列按层分开来,跟前面的直接打印二叉树每层思路一样,只是现在要判断奇数层和偶数层,然后反转对应的ArrayList即可!public class Solution { public class ...原创 2018-09-17 16:14:06 · 143 阅读 · 0 评论 -
序列化和反序列化二叉树
题目描述请实现两个函数,分别用来序列化和反序列化二叉树。序列化二叉树二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、按层 的二叉树遍历方式来进行修改。原理都是一样的(即遍历顺序不同而已,对每个结点的处理都是一样的),序列化的结果是一个字符串,序列化时通过某种符号表示空节点(#),以 !...原创 2018-09-18 13:52:14 · 436 阅读 · 0 评论 -
二叉搜索树的第k个结点
题目给定一颗二叉搜索树,请找出其中的第k大的结点。例如按结点数值大小顺序第三个结点的值为4。思路利用二叉搜索数中序遍历有序的特点,用递归和迭代分别实现中序遍历。package com.zhumq.leetcode;import java.util.Stack;public class KthNode { public class TreeNode{ TreeNode left...原创 2018-09-18 14:23:55 · 272 阅读 · 2 评论 -
数据流中的中位数
题目描述如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。思路1维护一个数组,每次加入后,进行排序,当总元素个数为奇数时,中位数就是数组中间的元素;当总元素个数为偶数时,中位数就是数组中间元素和前一个元素的平均数。思路2Java 1.5版本后就提供了一...原创 2018-09-18 15:27:59 · 181 阅读 · 0 评论 -
滑动窗口的最大值
题目思路1暴力求解法,扫描滑动窗口中的每一个数字,并找出其中的最大值。如果滑动窗口的大小为m,则找到窗口内的最大值需要O(k)时间。对于长度为n的数组,总的时间复杂度为O(mn)思路2借助一个辅助队列,从头遍历数组,根据如下规则进行入队列或出队列操作:如果队列为空,则当前数字入队列如果当前数字大于队列尾,则删除队列尾,直到当前数字小于等于队列尾,或者队列空,然后当前数字入队列如果当...原创 2018-09-19 11:46:51 · 213 阅读 · 0 评论 -
机器人的运动范围
题目请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中任意一格开始,每一步可以在矩阵中间向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。举例分析例如在下面的 3*4 的矩阵中包含一条字符串“bcced”的路径。但矩阵中不包含字符串“abcb”的路径,因为字符串的第一个字符 b 占据了矩阵中的第一行第二格子之后,...原创 2018-09-20 19:34:41 · 211 阅读 · 0 评论