剑指offer
weidiezeng
android
展开
-
48.最长不包含重复字符的字符串
题目:请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长字符串的长度。假设字符串只包含’a’~'z’的字符。例如,在字符串“arabacafr”中,最长的不包含重复字符的子字符串是“acfr”,长度为4。基本思路:首先定义函数f(i)表示以第i个字符为结尾的不包含重复字符的子字符串的最长长度。循环判断到第i个字符时,如果第i个字符之前没出现过,那么f(i)=f(i-1)+1;如...原创 2019-12-23 21:21:28 · 108 阅读 · 0 评论 -
57.和为s的数字
题目:输入一个递增排序的数组和一个数字s,在数组中查找两个数,得它们的和正好是s。如果有多对数字的和等于s,输出任意一对即可。举例说明,例如输入数组{1 、2 、4、7 、11 、15 }和数字15. 由于4+ 11 = 15 ,因此输出4 和11 。基本思路:我们先在数组中选择两个数字,如果它们的和等于输入的s,我们就找到了要找的两个数字。如果和小于s 呢?我们希望两个数字的和再大一点。由于...原创 2019-09-12 17:02:12 · 83 阅读 · 0 评论 -
54.二叉搜索树的第k大节点
题目:给定一棵二叉搜索树,请找出其中第k大节点。基本思路:由二叉搜索树特性可知,中序遍历正是它的递增排序。因此只需要用中序遍历去遍历一棵二叉搜索树,就能找到第k大节点。java实现:public class FindKInTree { public static class BinaryTreeNode { int value; Binary...原创 2019-09-15 10:47:31 · 62 阅读 · 0 评论 -
58.翻转字符串
题目一:翻转单词顺序。输入一个英文句子,翻转句子中单词的顺序,但单词内字的顺序不变。为简单起见,标点符号和普通字母一样处理。举例说明例如输入字符串”I am a student. ”,则输出”student. a am I”。基本思路:第一步翻转句子中所有的字符。比如翻转“I am a student. ”中所有的字符得到”.tneduts a m a I”,此时不但翻转了句子中单词的顺序,连...原创 2019-09-15 15:20:54 · 98 阅读 · 0 评论 -
59.队列的最大值
题目:给定一个数组和滑动窗口的大小,请找出所有滑动窗口里的最大值。举例说明,例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小为3,那么一共存在6个滑动窗口,它们的最大值分别为{4,4,6,6,6,5}。基本思路:如果采用蛮力法,这个问题似乎不难解决:可以扫描每一个滑动窗口的所有数字并找出其中的最大值。如果滑动窗口的大小为k,需要O(k)时间才能找出滑动窗口里的最大值。对...原创 2019-09-15 16:44:37 · 107 阅读 · 0 评论 -
60.n个骰子的点数
题目:把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s 的所有可能的值出现的概率。基本思路解法一:基于递归求解,时间效率不够高。先把n个骰子分为两堆:第一堆只有一个,另一个有n- 1 个。单独的那一个有可能出现从1 到6 的点数。我们需要计算从1 到6 的每一种点数和剩下的n-1 个骰子来计算点数和。接下来把剩下的n-1个骰子还是分成两堆,第一堆只有一个, 第二堆有...原创 2019-09-16 13:38:21 · 270 阅读 · 0 评论 -
61.扑克牌中的顺子
题目:从扑克牌中随机抽5张牌,判断是不是一个顺子, 即这5张牌是不是连续的。2~10为数字本身, A为1。 J为11、Q为12、 为13。小王可以看成任意数字。基本思路:我们可以把5张牌看成由5个数字组成的数组。大、小王是特殊的数字,我们不妨把它们都定义为0,这样就能和其他扑克牌区分开来了。接下来我们分析怎样判断5个数字是不是连续的,最直观的方法是把数组排序。值得注意的是,由于0可以当成...原创 2019-09-16 15:22:35 · 319 阅读 · 0 评论 -
62.圆圈中最后剩下的数字(约瑟夫环问题)
题目:0, 1, … , n-1 这n个数字排成一个圈圈,从数字0开始每次从圆圏里删除第m个数字。求出这个圈圈里剩下的最后一个数字。基本思路:创建一个总共有n 个结点的环形链表,然后每次在这个链表中删除第m 个结点。java实现:public class LastRemaining { public static int lastRemaining(int n,int m) {...原创 2019-09-16 15:46:36 · 77 阅读 · 0 评论 -
33.二叉搜索树的后序遍历序列
题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回true。否则返回false。假设输入的数组的任意两个数字都互不相同。基本思路:在后序遍历得到的序列中, 最后一个数字是树的根结点的值。数组中前面的数字可以分为两部分: 第一部分是左子树结点的值,它们都比根结点的值小: 第二部分是右子树结点的值,它们都比根结点的值大。java实现:public clas...原创 2019-09-20 19:50:44 · 80 阅读 · 0 评论 -
42.连续子数组的最大和
题目:输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。例子说明:例如输入的数组为{1, -2, 3, 10, -4, 7, 2, -5},和最大的子数组为{3, 10, -4, 7, 2}。因此输出为该子数组的和18 。基本思路:解法一:举例分析数组的规律。我们试着从头到尾逐个累加示例数组中的每个数字。初...原创 2019-09-20 20:34:59 · 51 阅读 · 0 评论 -
9.用两个栈实现队列
题目:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail 和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能。基本思路:栈1用于存储元素,栈2用于弹出元素,负负得正。说的通俗一点,现在把数据1、2、3分别入栈一,然后从栈一中出来(3、2、1),放到栈二中,那么,从栈二中出来的数据(1、2、3)就符合队列的规律了,即负负得正。Java实现:...原创 2019-09-21 11:10:02 · 80 阅读 · 0 评论 -
11.旋转数组的最小数字
题目:把一个数组最开始的若干个元素搬到数组的末尾, 我们称之数组的旋转。输入一个递增排序的数组的一个旋转, 输出旋转数组的最小元素。例如数组{3,4,5,1,2 }为{ 1,2,3,4,5}的一个旋转,该数组的最小值为1。基本思路:Step1.和二分查找法一样,我们用两个指针分别指向数组的第一个元素和最后一个元素。Step2.接着我们可以找到数组中间的元素:如果该中间元素位于前面的递增...原创 2019-09-21 14:53:56 · 57 阅读 · 0 评论 -
63.股票的最大利润
题目:假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?例如,一只股票在某些时间节点的价格为{9,11,8,5,7,12,16,14}。如果我们能在价格为5的时候买入并在价格为16时卖出,则能收获的最大利润为11。基本思路:使用暴力法时间复杂度为O(n^2),肯定是超时的。换一种思路:我们先定义diff(i)为当卖出价为数组中第i个数字是可能获得的最大...原创 2019-09-22 10:12:11 · 118 阅读 · 0 评论 -
65.不用加减乘除做加法
题目:写一个函数,求两个整数之和,要求在函数体内不得使用+、-、×、÷四则运算符号。基本思路:5 的二进制是101, 17 的二进制是10001 。试着把计算分成三步:第一步各位相加但不计进位, 得到的结果是10100 ( 最后一位两个数都是1,相加的结果是二进制的10 )。这一步不计进位, 因此结果仍然是0 。第二步记下进位。在这个例子中只在最后一位相加时产生一个进位,结果是二进制的...原创 2019-09-22 10:52:32 · 60 阅读 · 0 评论 -
66.构建乘积数组
题目:给定一个数组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],不能使用除法。基本思路:B[i]的值可以看作下图的矩阵中每行的乘积。下三角用连乘可以很容求得,上三角,从下向上也是连乘。因此我们的思路就很清晰了,先算下三角中的连乘,即我们先算出B[i]中的一部分,然后倒过...原创 2019-09-22 14:41:56 · 89 阅读 · 0 评论 -
67.把字符串转换为整数
题目:实现一个函数stringToInt,实现把字符串转换成整数这个功能,不能使用atoi或者其他类似的库函数。基本思路:这看起来是很简单的题目,实现基本功能 ,大部分人都能用10行之内的代码解决。可是,当我们要把很多特殊情况即测试用例都考虑进去,却不是件容易的事。解决数值转换问题本身并不难,但我希望在写转换数值的代码之前,应聘者至少能把空指针,空字符串”“,正负号,溢出等方方面面的测试用...原创 2019-09-23 15:44:34 · 124 阅读 · 0 评论 -
68.树中两个节点的最低公共节点
题目:求树中两个结点的最低公共祖先,此树不是二叉树,并且没有指向父节点的指针。基本思路我们首先得到一条从根结点到树中某一结点的路径,这就要求在遍历的时候,有一个辅助内存来保存路径.比如我们用前序遍历的方法来得到从根结点到H 的路径的过程是这样的:( 1 )遍历到A,把A 存放到路径中去,路径中只有一个结点A; ( 2 )遍历到B,把B 存到路径中去,此时路径为A->B; ( ...原创 2019-09-23 19:04:07 · 212 阅读 · 0 评论 -
15.二进制中1的个数
题目:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如把9表示成二进制1001,有2位1。因此如果输入9,该函数输出2。基本思路:解法一:首先把n和1做与运算,判断n的最低位是不是1。接着把1左移一位得到2,再和n做与运算,就能判断次低位是不是1...这样反复左移,每次都能判断n的其中一位是不是1。在这个解法中,循环的次数等于整数二进制表示的位数。解法二:循环让(n -...原创 2019-10-05 13:26:30 · 111 阅读 · 0 评论 -
56.数组中只出现一次的数字
题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次,请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。举例说明,例如输入数组{2, 4, 3, 6, 3, 2, 5 },因为只有4 、6 这两个数字只出现一次,其他数字都出现了两次,所以输出4和6 。基本思路:这两个题目都在强调一个(或两个)数字只出现一次,其他的出现两次。这有什么意义呢?我们想到...原创 2019-09-12 16:01:43 · 108 阅读 · 0 评论 -
55.判断平衡二叉树
题目:输入一棵二叉树的根结点,判断该树是不是平衡二叉树。如果某二叉树中任意结点的左右子树的深度相差不超过1 ,那么它就是一棵平衡二叉树。基本思路:解法一:需要遍历结点多次的解法在遍历树的每个结点的时候,调用函数treeDepth得到它的左右子树的深度。如果每个结点的左右子树的深度相差都不超过1 ,按照定义它就是一棵平衡的二叉树。解法二:每个结点只遍历一次的解法用后序遍历的方式遍历二...原创 2019-09-10 19:23:16 · 101 阅读 · 0 评论 -
4.二维数组中的查找
题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。基本思路:首先选取数组中右上角的数字。如果该数字等于要查找的数字,查找过程结束。如果该数字大于要查找的数字,剔除这个数字所在的列:如果该数字小于要查找的数字,剔除这个数字所在的行。也就是说如果要查找的数字不在数组的右上角,则...原创 2019-07-20 15:19:46 · 128 阅读 · 0 评论 -
13.机器人的运动范围
题目:地上有个m行n列的方格。一个机器人从坐标(0,0)的格子开始移动,它每一次可以向左、右、上、下移动一格,但不能进入行坐标和列坐标的数位之和大于k的格子。 举例分析:例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7=18.但它不能进入方格(35,38),因为3+5+3+8=19.请问该机器人能够达到多少格子?基本思路:这个方格也可以看出一个m...原创 2019-07-20 16:36:07 · 67 阅读 · 0 评论 -
17.打印从1到最大的n位数
题目:输入数字n,按顺序打印出从1到n位最大十进数的数值。比如输入3,则打印出1、2、3一直到最大三位数即999。基本思路:解法一:用数组存储大数,首先初始化为0,然后为每一个数组元素表示的数字加1,再打印出来。因此我们只需要做两个事情:一是在数组表达的数字上模拟加法;二是:把数组表达的数字打印出来;解法二:如果我们在数字前面补0,就会发现n位所有十进制其实就是n个从0到9的全排列。也...原创 2019-07-21 16:27:11 · 114 阅读 · 0 评论 -
22.链表中倒数第k个节点
题目:输入一个链表,输出该链表中倒数第k 个结点。为了符合大多数人的习惯,本题从1 开始计数,即链表的尾结点是倒数第1 个结点.例如一个链表有6 个结点,从头结点开始它们的值依次是1 、2、3、4、5 、6。这个链表的倒数第3 个结点是值为4 的结点。基本思路:解法一:假设整个链表有n个节点,那么倒数第k个节点就是从头节点开始的第n-k+1个节点。为了得到n的值,需要从头开始遍历链表。没经...原创 2019-08-04 10:52:53 · 1130 阅读 · 0 评论 -
24.反转链表
题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。链表定义如下:class Node<E> { E value; Node<E> nextNode; }基本思路:解法一:遍历。将指向下一个节点的指针指向上一个节点。(原链表的尾结点即是新链表的头节点)解法二:递归。先让指向下一个节点的指针为空,然后递归调用,最后再将指向下一个节点的...原创 2019-08-04 11:45:36 · 68 阅读 · 0 评论 -
25.合并两个排序的链表
题目:输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。、基本思路:解法一:递归比较两个链表的其余节点,让较小的节点作为上一个新节点的后一个节点;解法二:循环比较两个链表的其余节点,让较小的节点作为上一个新节点的后一个节点。直到有一个链表没有节点,然后将新链表的最后一个节点直接指向剩余链表的节点。解法一Java实现:public class Mer...原创 2019-08-05 10:00:07 · 85 阅读 · 0 评论 -
29.顺时针打印矩阵
题目:输入一个矩阵,按照从外向里以顺时针的顺序依次扫印出每一个数字基本思路:把打印一圈分为四步:第一步从左到右打印一行,第二步从上到下打印一列,第三步从右到左打印一行,第四步从下到上打印一列。每一步我们根据起始坐标和终止坐标用一个循环就能打印出一行或者一列。不过值得注意的是,最后一圈有可能退化成只有一行、只有一列,甚至只有一个数字,因此打印这样的一圈就不再需要四步。因此我们要仔细分...原创 2019-08-05 11:21:55 · 56 阅读 · 0 评论 -
31.栈的压入、弹出序列
题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等基本思路:解决这个问题很直观的想法就是建立一个辅助栈,把输入的第一个序列中的数字依次压入该辅助栈,并按照第二个序列的顺序依次从该栈中弹出数字。判断一个序列是不是栈的弹出序列的规律:如果下一个弹出的数字刚好是栈顶数字,那么直接弹出。如果下一个弹出的数字不在栈顶,我们把压栈序...原创 2019-08-05 12:43:50 · 60 阅读 · 0 评论 -
32.之字形打印二叉树
题目:请实现一个函数按照之字形打印二叉树,即第一行从左到右的顺序打印,第二行按照从右到左打印,第三行再按照从左到右的顺序打印,以此类推。基本思路:需要两个栈,我们在打印某一层的节点时,把下一层的节点保存到相应的栈中(先进后出,到时候按栈顶输出)。先保存根节点到第一个栈(存储奇数层节点),如果当前打印的是奇数层,则先保存左子节点再保存右子节点到第二个栈(存储偶数层节点);如果当前打印的是偶数层,...原创 2019-08-09 10:53:14 · 85 阅读 · 0 评论 -
34.二叉树中和为某值的路径
题目:输入一棵二叉树和一个整数, 打印出二叉树中结点值的和为输入整数的所有路径。从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。基本思路:由于路径是从根结点出发到叶结点, 也就是说路径总是以根结点为起始点,因此考虑使用前序遍历,只有前序遍历是首先访问根结点的。当用前序遍历的方式访问到某一结点时, 我们把该结点添加到路径上,并累加该结点的值。如果该结点为叶结点并且路径中结点值的和刚...原创 2019-08-27 10:41:56 · 55 阅读 · 0 评论 -
38.字符串的排列
题目:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc。则打印出由字符a、b、c 所能排列出来的所有字符串abc、acb、bac 、bca、cab 和cba基本思路:把一个字符串看成由两部分组成:第一部分为它的第一个字符,第二部分是后面的所有字符。我们求整个字符串的排列,可以看成两步:首先求所有可能出现在第一个位置的字符,即把第一个字符和后面所有的字符交换。这个时候我...原创 2019-08-27 14:53:59 · 88 阅读 · 0 评论 -
39.数组中出现次数超过一半的数字
题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。基本思路:解法一:基于Partition 函数的O(n)算法。数组中有一个数字出现的次数超过了数组长度的一半。如果把这个数组排序,那么排序之后位于数组中间的数字一定就是那个出现次数超过数组长度一半的数字。也就是说,这个数字就是统计学上的中位数,即长度为n 的数组中第n/2 大的数字。这种算法是受快速排序算法的启发。在随机快...原创 2019-08-30 11:43:24 · 61 阅读 · 0 评论 -
43.1~n整数中1出现的次数
题目:输入一个整数n,求从1 到n这n个整数的十进制表示中1 出现的次数。举例说明:例如输入12 ,从1 到12 这些整数中包含1 的数字有1、10、11 和12,1 一共出现了5 次。基本思路:解法一:不考虑时间效率的解法累加1 到n 中每个整数中1出现的次数。我们可以每次通过对10 求余数判断整数的个位数字是不是1 。如果这个数字大于10,除以10 之后再判断个位数字是不是1 ...原创 2019-09-02 11:40:20 · 144 阅读 · 0 评论 -
45.把数组排成最小的数
题目:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例子说明:例如输入数组{3,32, 321},则扫描输出这3 个数字能排成的最小数字321323基本思路:解法一:直观解法先求出这个数组中所有数字的全排列,然后把每个排列拼起来,最后求出拼起来的数字的最小值。解法二:排序解法找到一个排序规则,数组根据这个规则排序之后能排成一个最小的...原创 2019-09-03 16:48:17 · 85 阅读 · 0 评论 -
49.丑数
题目:我们把只包含因子2、3 和5 的数称作丑数(Ugly Number)。求从小到大的顺序的第1500个丑数。举例说明:例如6、8 都是丑数,但14 不是,它包含因子7。习惯上我们把1 当做第一个丑数。基本思路:解法一:逐个判断每个数字是不是丑数的解法,直观但不够高效解法二:根据丑数的定义, 丑数应该是另一个丑数乘以2、3 或者5 的结果(1除外)。因此我们可以创建一个数组,里面...原创 2019-09-05 11:22:00 · 74 阅读 · 0 评论 -
52.两个链表的第一个公共子节点
题目:输入两个链表,找出它们的第一个公共结点基本思路:解法一:直接法在第一个链表上顺序遍历每个结点,每遍历到一个结点的时候,在第二个链表上顺序遍历每个结点。如果在第二个链表上有一个结点和第一个链表上的结点一样,说明两个链表在这个结点上重合,于是就找到了它们的公共结点。如果第一个链表的长度为m,第二个链表的长度为n,显然该方法的时间复杂度是O(mn) 。解法二:使用栈所以两个有公共结...原创 2019-09-09 16:49:20 · 228 阅读 · 0 评论 -
53.在排序数组中出现的数字
题目:统计一个数字:在排序数组中出现的次数。举例说明例如输入排序数组{ 1, 2, 3, 3, 3, 3, 4, 5}和数字3 ,由于3 在这个数组中出现了4 次,因此输出4 。基本思路:利用改进的二分算法。如何用二分查找算法在数组中找到第一个k,二分查找算法总是先拿数组中间的数字和k作比较。如果中间的数字比k大,那么k只有可能出现在数组的前半段,下一轮我们只在数组的前半段查找就可以了。如果中...原创 2019-09-09 22:02:34 · 70 阅读 · 0 评论 -
7.重建二叉树
题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如:前序遍历序列{ 1, 2, 4, 7, 3, 5, 6, 8}和中序遍历序列{4, 7, 2, 1, 5, 3, 8,6},重建二叉树并输出它的头结点。解题思路:由前序遍历的第一个节点可知根节点。根据根节点,可以将中序遍历划分成左右子树。在前序遍历中找出对应的左右...原创 2019-07-19 11:56:05 · 82 阅读 · 0 评论