剑指offer
文章平均质量分 51
yang20141109
这个作者很懒,什么都没留下…
展开
-
用两个栈实现队列
题目:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列的尾部插入节点和在队列的头部删除节点的功能。解析:队列的特点是先进先出,而栈的特点是后进先出。首先,我们声明两个栈s1和s2,入队列的元素,我们都插入在s1中。出队列的元素,我们都从s2中进行弹出元素。也就是appendTail操作只在s1中进行,deleteHead(int原创 2015-10-16 21:26:33 · 306 阅读 · 0 评论 -
和为S的两个数
题目:输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得他们的和正好是s.如果有多对数字的和等于s,输出任意一对即可。 例如输入数组{1,2,4,7,11,15}和数字15。由于4+11=15,因此输出4和11。 方法一:时间复杂度为o(n*n),首先在数组中固定一个数字,再依次判断数组中该元素之后的某个数字与它的和是不是等于s。vector FindNumbersW原创 2016-03-18 16:16:57 · 363 阅读 · 2 评论 -
和为s的连续正序列
题目:输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数)。例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以结果打印出3个连续序列1~5,4~6,7~8。 解析:我们考虑两个数small和big分别表示序列中的最小值和最大值。首先把small初始化为1,big初始化为2.如果small到big的序列之和大于s,我们可以从序列中去掉最小值,也就是增大smal原创 2016-03-18 16:31:05 · 401 阅读 · 0 评论 -
不使用乘法除法循环递归做累加操作
题目:求1+2+...+n,要求不能使用乘法除法、for、while、if、else、switch、case等关键字字及其条件判断语句。方法一:构造函数class Temp{private: static unsigned int num; static unsigned int sum;public: Temp(){ ++num; sum += num; } static原创 2016-03-21 22:09:23 · 708 阅读 · 1 评论 -
二叉树镜像(递归与非递归)
题目:请完成一个函数,输入一个二叉树,该函数输出它的镜像。如下图所示:右边的二叉树就是左边的树的镜像。我们可以根据照镜子的经验画出它的镜像。递归思想:这两棵树的根节点相同,但是他们的左右孩子交换了。首先,我们交换根节点的两个孩子,然后递归的处理根节点孩子的孩子。代码如下:void mirror01(BinaryTreeNode *root){ if(root == NULL)//处理的原创 2016-03-11 17:21:11 · 3142 阅读 · 1 评论 -
字符串中第一次出现的字符
题目:在字符串中查找出第一个只出现一次的字符。如输入"abaccdeff",则输出b所在的下标。方法一:时间复杂度为o(n*n)。遍历字符串中的每个字符,然后用该字符在字符串中进行查找,如果没有找到和当前字符相同的字符。则当前字符为第一个 只出现一次的字符。int firstNotRepeatingChar(string str){ if (str.empty()) return -1原创 2016-03-27 09:25:12 · 2395 阅读 · 0 评论 -
顺时针打印矩阵
题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如:如果输入的矩阵如下图所示:则顺时针打印的序列为:1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10。 解析:我们可以一圈一圈的打印矩阵,要一圈一圈的打印矩阵,必须获得圈的边界:圈的起始行和终止行,以及圈的起始列和终止列。打印的结束条件是:(1)起始行和终止行相同。(2)起始列和终止原创 2016-05-25 21:34:25 · 369 阅读 · 0 评论 -
调整数组使得奇数元素位于偶数元素之前(相对位置不变)
调整数组,使得奇数元素位于偶数元素之前,且相对顺序不变。解析:冒泡排序思想,比较当前元素和下一个元素,如果当前元素是偶数且下一个元素为奇数,交换这两个数。每次冒泡都会使得最后一个偶数在正确的位置。void reOrderArray(vector &nums) { int size = nums.size(); for (int i = 0; i < size - 1; ++i) {原创 2016-07-14 17:21:18 · 1390 阅读 · 0 评论 -
栈的压入和弹出序列
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的) 解析:使用辅助栈,压入序列中元素依次入栈,每次入栈时,判断当前栈顶元素是否和弹出序列中元素原创 2016-07-14 21:15:36 · 347 阅读 · 0 评论 -
二叉树的深度(递归和非递归)
给定一个二叉树,求此二叉树的深度。递归方法:int TreeDepth(TreeNode* pRoot){ if (pRoot == NULL) return 0; if (pRoot->left == NULL && pRoot->right == NULL) return 1; return max(TreeDepth(pRoot->left), TreeDepth(pRo原创 2016-07-18 15:36:39 · 3301 阅读 · 0 评论 -
连续子数组的最大和
题目:输入一个整型数组,数组里面有正数也有负数。数组中一个或连续的多个整数组成一个子数组,求所有子数组的和的最大值。要求时间复杂度为o(n)。 解析:例如输入的数组为{1,-2,3,10,-4,7,2,-5},和最大的子数组为{3,10,-4,7,2},因此输出为该子数组的和18。 方法一:时间复杂度为o(n*n*n)的解法,枚举数组的所有子数组并求出它们的和。int Find原创 2016-03-18 12:04:49 · 347 阅读 · 0 评论 -
数组中的逆序对
题目:在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。 解析:例如在数组{7,5,6,4}中,一共存在5个逆序对,分别是(7,6)、(7,5)、(7,4)、(6,4)和(5,4)。解法一:交换排序的思想,在交换排序中如果前面的数字大于后面的数字,那么这两个数字需要交换一次,证明原数组有一个逆序对,直到数组有序为原创 2016-03-18 11:47:33 · 375 阅读 · 0 评论 -
旋转数组的最小值
题目:把一个数组的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小值。例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1。解析:(1)我们可以用顺序查找的方法找到数组中的最小值,但是这个方法没有用到旋转数组局部有序的特点。(2)和二分查找法一样,我们用两个指针分别指向数组的第一个元素和最后原创 2015-10-17 21:44:49 · 275 阅读 · 0 评论 -
用两个队列实现栈
题目:用两个队列实现栈的三个基本操作,(1)出栈操作pop。(2)入栈操作push。(3)返回栈顶元素top()。解析:栈是先进后出,队列是先进先出。首先定义两个队列q1和q2,当进行入栈操作时,有两种情况:(1)q1和q2两者都为空,把入栈的元素插入到q1和q2中的任意一个。(2)如果q1(q2)不为空,把入栈元素插入到q1(q2)队尾。当进行出栈操作时,有两种情况:(1)q1和q2都为空,原创 2015-10-16 22:24:23 · 320 阅读 · 0 评论 -
二进制中1的个数
题目:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如把9表示成二进制是1001,有2位是1。因此如果输入9,该函数输出2。方法一:int oneNum01(int num){ int count = 0;//记录二进制中1的个数 while(num) { if(num % 2)//最后一位是1 count++; num = num >> 1;//原始的n原创 2015-10-19 19:53:25 · 352 阅读 · 0 评论 -
【剑指offer】1.二维数组中的查找
题目:在一个二维数组中,元素从左到右、从上到下都是递增,给定一个元素value,判断这个元素是否出现在二维数组中。比如二维数组如下:1 2 8 92 4 9 124 7 10 136 8 11 15如果我们首先和数组中的第一个元素比较,(要找3,是否在二维数组中出现,我们不知道要向右进行查找,还是向左进行查找)所以从二维数组首元素进行查找,此方法不能在确定下次到原创 2015-07-30 21:29:07 · 391 阅读 · 0 评论 -
打印1到最大的n位数
题目:输入数字n,按照顺序打印出从1到最大的n位十进制数,比如输入3,则打印出1、2、3一直到最大的3位数即999。 解析:我们很容易写出以下的代码,当我们输入的n很大的时候,我们求得的最大n位数不能用int类型或者long long类型表示时,以下代码将会有缺陷。void printOneToMax(int n){ int number= 1; for(int i = 0; i原创 2016-01-16 19:36:37 · 363 阅读 · 0 评论 -
调整数组顺序使奇数位于偶数之前
题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。 方法一:快排算法的思想,选择一个枢轴,该枢轴把数组分成前后两半部分,使得前半部分的数值小于枢轴值,后半部分的数值大于枢轴值。如果我们按照此思想,使得奇数位于前半部分,偶数位于后半部分。我们只需要扫描一次数组就可以。时间复杂度为o(n)。代码如下:#includeu原创 2016-01-16 20:35:42 · 317 阅读 · 0 评论 -
替换空格
题目:请实现一个函数,把字符串中的每个空格替换成"%20"。例如输入"we are happy",则输出"we%20are%20happy"。 方法一:创建新的字符串并在新的字符串上做替换操作,那么我们自己可以分配足够多的内存,用来容纳新的字符串。时间复杂度为o(n)。#includeusing namespace std;//替换空格为%20char* replace(char原创 2016-01-05 10:25:02 · 294 阅读 · 0 评论 -
数值的整数次方
题目:实现函数double power(double base,int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。解析:我们可以很快就写出一下的代码。不过遗憾的是,写得快不一定就对,如果输入的指数(exponent)小于1即是零和负数的时候怎么办。下面代码只考虑指数为正数的情况。double power(double base,int exp原创 2016-01-12 15:38:28 · 396 阅读 · 0 评论 -
二叉树的子结构
题目:输入两棵二叉树A和B,判断B是不是A的子结构。 解析:要查找树A中是否存在和树B结构一样的子树,我们可以分为两步:第一步在树A中找到和树B根节点的值一样的节点R,第二步再判断树A中以R为根节点的子树是不是包含和树B一样的结构。 第一步在树A中查找与根节点的值一样的节点,这实际上就是树的遍历。我们可以使用递归的方法遍历二叉树。代码如下:bool hasSubtree(Bin原创 2016-03-01 12:00:43 · 284 阅读 · 0 评论 -
不使用加减乘除做两个数加法
题目:不使用加减乘除做两个数的加法,比如num1=4和num2=5,两个数做完加法以后为9。 解析:因为不能使用四则运算,我们可以考虑使用位操作。首先:计算num1和num2异或。然后:计算两个数的与操作并且向左移动一位。两步分别计算出二进制中相同位为1和相同位一个为一另一个为零的情况。int Add(int num1, int num2){ int sum = num1; whi原创 2016-07-19 16:32:11 · 412 阅读 · 0 评论