剑指offer
文章平均质量分 71
Hi丨OwO丨gx
这个作者很懒,什么都没留下…
展开
-
51、链表的环的入口结点
题目描述:一个链表中包含环,请找出该链表的环的入口结点。解法: 假如从头结点1出发,2为环的入口,3为相遇的点。 1到2 距离为a ,2到3距离为b ,3到2距离为c有两个跟进节点同时前进,p1一次前进一步,p2一次前进两步。最终相遇在3. 则有 p1前进的距离:a+bp2前进的距离: a+b+(c+b)其中p2比p1多走了一个环的距离,且速度为p1的两倍,即距离刚好还是p1的两倍所以有a+b...原创 2018-06-28 11:22:42 · 147 阅读 · 0 评论 -
48、构建乘积数组
题目:给定数组A[n],构建一个数组B[n],B[i] = A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1],要求不用除法实现。解法:把数组A[n]以A[i]为界限分成左半段和右半段。每一侧都用一个循环求相应的值即可例如。有两个辅助数组help1和help2.在求B[5]时候。help1=A0*A1*A2*A3*A4 ,help2=A6*A7*...*A[n-1]每一个...原创 2018-04-03 10:26:01 · 207 阅读 · 0 评论 -
19、从上到下打印二叉树(层次遍历)
题目:从上到下打印出二叉树的每个节点,同层节点从左至右打印。解法:1、实质就为二叉树的层次遍历。2、用一个队列,依次记录当前节点的左右子节点。3、循环让队列pop出元素,直到队列为空,即遍历完毕。代码如下: vector<int> PrintFromTopToBottom(TreeNode* root) { vector<int> res; ...原创 2018-03-28 09:14:02 · 277 阅读 · 0 评论 -
18、栈的压入、弹出序列
题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数组均不相等,例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是对应的一个弹出顺序。但是4,3,5,1,2就不是弹出顺序。说明:第一次见这个题目,有点没懂说明意思。在这里说明一下。出栈是指在压入任意一个数字的时候都可以进行出栈操作,并且出栈的数组数量也可以为任意个。例如:题目...原创 2018-03-28 09:05:54 · 98 阅读 · 0 评论 -
47、数组中重复的数字
题目:一个长度为n的整数数组,里面的元素 大小范围在0~n-1之间,请判断是否有重复数字,若有请返回任意一个重复元素。解法:1、利用哈希表2、不用哈希表,利用题目中数组的特性:大小范围在0~n-1之间代码如下:(动态数组的哈希表) bool duplicate(int numbers[], int length, int* duplication) { duplication...原创 2018-04-03 09:46:33 · 174 阅读 · 0 评论 -
46、将字符串转换成整数
题目:将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数,数值为0或者字符串不是一个合法的数值返回0.解法:1、充分考虑不同的输入情况和异常输入的情形。2、首字符可以为0~9、‘+’、‘-’字符。3、后面的字符必须为0~9之间的字符。4、""、空字符串、和非法输入的 输出为0代码如下: int StrToInt(string str) { if(str.size(...原创 2018-04-03 09:01:01 · 210 阅读 · 0 评论 -
17、实现包含min函数的最小栈
题目:定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。解法:利用两个栈实现,stack1和stack2. stack1实现栈的基本功能pop();top()等,Stack2实现Min()功能,每当一个元素value压入stack1中时候,比较value 和 stack2.top()元素,把min(value,stack2.top())再压入stack2中,相当于在stack2...原创 2018-03-27 16:07:29 · 111 阅读 · 0 评论 -
16、顺时针打印矩阵
题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。例如矩阵为,输出后的结果为[1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10]解法:1、求取数组的row和col ,利用循环,每次输出一个圆 来逐次输出所有数据。初始化circleNum=0,那么每一圈开始位置为matrix[circleNum][circleNum],即第一圈开始的位置在数组中的索引。...原创 2018-03-27 15:50:51 · 182 阅读 · 0 评论 -
15、求给定二叉树的镜像二叉树
题目:操作给定的二叉树,将其变换成原二叉树的镜像解法:1、整体为遍历二叉树。本题及假设采用了前序遍历。2、在遍历过程中,如果该节点存在 子节点,则交换子节点即可。代码如下: void Mirror(TreeNode *pRoot) { if(pRoot ==NULL) return; TreeNode* temp; if...原创 2018-03-27 14:42:51 · 210 阅读 · 0 评论 -
45、不用加减乘除做加法
题目:求两个整数的和,要求函数中不能使用+、-、*、/ 四则运算符号。解法:1、考虑到整数的运算不能使用加减乘除,那么只有位运算可以使用。2、将a+b转换成add(c,d)的模式。其中c为a+b在二进制表达的过程中未进位的结果。d为a+b在二进制表达中进位的结果。举例:例如a = 10101 ,b=10001; 首先利用a^b得到未进位的结果。即在二进制表达中0+1=1+0=1,0+0=1+1=0...原创 2018-04-02 16:05:43 · 183 阅读 · 0 评论 -
44、求1+2+3+...+n
题目:求1+2+3+...+n,要求不能使用乘除,for while,if else switch case等关键字和条件判断句(A?B:C)解法:1、提供的是逻辑短路的代码。2、剑指OFFER书提供了多种解法。例如利用构造函数、利用虚函数、函数指针等。 int Sum_Solution(int n) { int ans = n; ans &&am...原创 2018-04-02 15:45:02 · 133 阅读 · 0 评论 -
14、树的子结构判断
题目:输入两颗二叉树A,B, 判断B是否为A的子结构(注意约定空树不是任意一颗树的子结构)解法:1、遍历A树节点,寻找节点值和B树根节点值相同的节点。2、对于步骤1中寻找的节点,判断以该节点为根的子树 是否存在和B一样的子树结构。3、注意异常输入 和NULL 的判断代码如下: bool HasSubtree(TreeNode* A, TreeNode* B) { bo...原创 2018-03-27 11:40:31 · 153 阅读 · 0 评论 -
最长公共子串与最长公共子序列问题
题目:1、最长公共子串问题(子串:连续的字符串)str ="abcde",“ab”"cd"都为子串2、最长公共子序列问题(子序列:保证相对顺序即可)str="abcde","ac" ,"ae"都为子序列。在概念上可以说,子串是特殊的子序列。假定有字符串str A , lenA = n, str B , lenB =m;解法:两个题目都是动态规划问题。最长子串的问题,因为是子串是连续的。dp[i][...原创 2018-04-10 16:26:19 · 190 阅读 · 0 评论 -
20、二叉搜索树的后续遍历序列
题目:输入一个整数数组,判断该数组是否为某二叉树的后续遍历结果,如果是输出true,否为false。假设输入中任意两个数字都不相同。例如 5,7,6,9,11,10,8 可以为一个后续遍历结果。其中5,7,6,为左子树,9,11,10为右子树,8为根解法:1、二叉搜索树后续遍历序列:(左)(右)根,且左<根<右。序列中的数字大小关系如左边所示。2、利用循环法。3、利用递归法。(一)循环...原创 2018-03-28 10:09:28 · 144 阅读 · 0 评论 -
50、表示数值的字符串
题目描述:请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。解法:思想类似题目49:正则表达式匹配问题。利用地柜逐原创 2018-06-28 11:17:51 · 161 阅读 · 0 评论 -
49.正则表达式匹配问题
问题描述:请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配已知:bool match(char* str, char* pattern)解法:利用递归思...原创 2018-06-28 11:10:17 · 455 阅读 · 0 评论 -
28、整数中1出现的次数
题目:求出1~n之间的整数中1出现的次数。其中n为任意非负整数。解法:注意是出现的次数:例如数字11,1出现的次数为2次。1、本题的思想是从最低位开始求1出现的次数。2、然后把所有位1出现的次数相加。eg:n=12345,( n=abcde ) 例如要求百位为1的数字的个数。一共分两步走。先求0~12299 中百位 为1的数字。再求12300~12345中百位为1的数字。(一)0~12299 中...原创 2018-03-29 16:07:17 · 121 阅读 · 0 评论 -
27、连续子数组的最大和
题目:输入一个整型数组,数组里面有正数和负数,数组中一个或连续的多个整数形成的一个子数组,求所有子数组的和的最大值。要求时间复杂度为o(n)。(子数组的长度至少为1)解法:1、动态规划做法。2、先初始化到a[0]的子数组的最大和,依次求到a[1]的子数组的最大和代码如下: int FindGreatestSumOfSubArray(vector<int> array) { ...原创 2018-03-29 14:39:21 · 95 阅读 · 0 评论 -
26、最小的k个数
题目:输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8则最小的4个数字为1,2,3,4解法:1、本题思想主要是堆排序。当然如果直接对所有数字使用堆排序或者快排,时间复杂度为o(n*logn)2、本题利用改进的堆排序,时间复杂度为o(n*logk)3、主要思想为:(一)提取数组中的前k个数,构建k个数初始大根堆heap,即heap[0]为前k个数中最大的值(二)利用遍历,从...原创 2018-03-29 14:13:16 · 109 阅读 · 0 评论 -
25、数组中出现次数超过一半的数字
题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。若不存在该数字,则输出0.解法:1、利用阵地法思想。2、以数组第一个数上阵地,阵地上的数字记为res,把阵地上的数字数量记为count,3、从array[2,....n-1]开始逐一上数来PK,若两个数一样,count++,不一样就--,4、出现count==0 的情况,令新来的为阵地上的数字res。5、直到最后,若存在一个数字A...原创 2018-03-29 13:37:04 · 123 阅读 · 0 评论 -
24、字符串的排列
题目:输入一个字符串,按字典序打印出该字符串中字符的所有排列,例如,输入字符串abc,打印出abc,acb,bac,bca,cab,cba.解法:将字符串看成两部分,首字母和剩下的字符串。即str = str[0]+str[1,2..n-1]然后利用递归,依次把首字母和后面的字母进行交换即可。代码: vector<string> Permutation(string str) {...原创 2018-03-29 11:27:10 · 110 阅读 · 0 评论 -
23、二叉搜索树与双向链表
题目:输入一颗二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。解法:二叉搜索树的中序遍历(左,根,右)形成的就是一个排序的结构。因此整体利用二叉树的中序遍历。在遍历过程中修改left和right指向即可。代码: TreeNode* Convert(TreeNode* pRootOfTree) { if(pRoo...原创 2018-03-29 10:00:57 · 89 阅读 · 0 评论 -
22、复杂链表的复制
题目:输入一个复杂链表(每个节点中又节点值,以及两个指针,一个指向下一个节点,一个指向任意节点)返回结果为复制后复杂链表的head。解法:(一)先复制每一个节点以及每一个节点的next指针,再从头遍历每一个节点,记录它们的random节点,再head遍历节点寻找random节点所在的位置。这样会用两个循环进行。时间复杂度o(n^2)(二)1、先复制每一个节点以及每一个节点的next指针。 ...原创 2018-03-29 09:06:23 · 106 阅读 · 0 评论 -
最长公共子括号序列
题目:输入包括字符串s(4 ≤ |s| ≤ 50,|s|表示字符串长度),保证s是一个合法的括号匹配序列。如样例所示: s = "(())()",跟字符串s长度相同的合法括号匹配序列有: "()(())", "((()))", "()()()", "(()())",其中LCS( "(())()", "()(())" )为4,其他三个都为5,所以输出3. 解法:1、取出原原创 2018-04-10 20:40:31 · 284 阅读 · 0 评论 -
21、二叉树中和为某一个值的路径
题目:输入一颗二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。路径:从根节点出发到叶节点形成的一条路径。解法:1、利用栈的原理。将前序遍历将节点压入栈中后,利用递归检查完其左右节点形成的路径是否满足题目要求后返回。2、子节点检查完毕后,弹出对应的根节点。代码如下: vector<vector<int> > FindPath(TreeNode* root...原创 2018-03-28 10:45:57 · 103 阅读 · 0 评论 -
13、合并两个排序好的链表
题目:输入两个单调递增的链表,输出两个链表合成后的链表,合成后的链表也为单调不递减规则。解法:1、实质就是一个归并排序中的merge过程(将两个排序好的相邻小序列合并成一个大序列)。2、分别采用递归和不递归的代码实现。3、注意边界条件和异常(仍然是考虑参数的输入,ListNode* Merge(ListNode* pHead1, ListNode* pHead2)) 参数有两个,分别考虑 -...原创 2018-03-27 11:02:15 · 89 阅读 · 0 评论 -
12、反转链表
题目:输入一个链表,反转链表后,输入反转后的链表的头结点。解法:1、利用画图,想好每一步的关系。利用三个变量pre,cur,next。pre为当前节点cur反转后的下一个节点即反转后cur->next = pre; next用来记录原链表中cur的下一个节点。2、考虑好异常情况。(还是从函数 参数出发。 当前函数参数为ListNode* pHead,即考虑pHead==NULL和链表只有一个...原创 2018-03-27 10:38:08 · 98 阅读 · 0 评论 -
11、寻找链表中倒数第k个节点
题目:输入一个链表,输出该链表中倒数第k个节点。解法:1、只遍历一次链表完成。2、利用两个指针first,second。先让first前进k-1步,之后前移first 和second,放first到达尾节点时候,second即为倒数第k个节点。3、注意边界和异常的判断: (一)头节点为空的情况 (二)k取值比链表长度大的情况代码如下:(通常边界条件的考察可以从下面入手 1.分别考...原创 2018-03-27 10:22:54 · 574 阅读 · 0 评论 -
6、求旋转数组的最小数字
题目:旋转数组:把数组的前一部分放到数组的末尾,称为旋转数组eg:数组【3,4,5,1,2】为数组[1,2,3,4,5]的旋转数组。输入一个(非递减)数组的一个旋转数组,求该数组的最小元素,若数组大小为0,返回0解法:普通解法:遍历数组,求取数组的最小元素,时间复杂度O(n),不作解释,不贴代码了二分查找法:时间复杂度为O(logn),下面对二分查找的方法进行说明。1、利用left,right,m...原创 2018-03-26 19:03:19 · 110 阅读 · 0 评论 -
7、斐波那契数列(青蛙跳问题)
题目:1、求第n项斐波那契数列的值。2、一只青蛙一次可以跳1级或2级台阶,问跳上n级台阶有多少种跳法。斐波那契数列:形如1,1,2,3,5,8.....的数列,其中第一项和第二项为1,其他项为f(n) = f(n-1)+f(n-2)解法:利用循环即可。初始化第0项为0,第一项为1,后面f(n) = f(n-1)+f(n-2) .代码如下: int Fibonacci(int n) { ...原创 2018-03-26 19:21:28 · 485 阅读 · 0 评论 -
8、二进制表示的数中1的个数
题目:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。解法:利用二进制方法。n = n & (n-1) ,得到n用二进制表示后,去掉最低位的1的数字。eg: n= 1111 0001 0000 ,经过上式后n=1111 0000 0000;代码如下: int NumberOf1(int n) { if(n==0) re...原创 2018-03-26 19:35:57 · 198 阅读 · 0 评论 -
37、数组中只出现一次的数字
题目:一个整型数组中除了两个数字以外,其他数字都出现了两次。请找出这个两个数字解法:1、利用异或原理。异或中又m^m=0,即两个相同的数字异或得0;2、该题目有一个简化版本为:一个整型数组中除了(一)个数字以外,其他数字都出现了两次。请找出这个一个数字!!answer: 对数组遍历异或,最后的结果即为只出现一次的数字。对于本题:以相同思想来处理。A、遍历数组异或,得到最后的结果为res, 假...原创 2018-03-31 10:14:09 · 101 阅读 · 0 评论 -
36、平衡二叉树
题目:输入一颗二叉树根节点,判断是否为平衡二叉树。平衡二叉树:首先平衡二叉树是一颗二叉排序树。再就是每一个非叶子节点的左右子树的高度差<=1;即左右子树也为平衡二叉树。解法:类似题目35.求左右子树的高度。在返回高度的过程中,利用一个变量记录左右子树的高度差的情况。代码如下: bool IsBalanced_Solution(TreeNode* pRoot) { if(...原创 2018-03-31 09:41:02 · 191 阅读 · 0 评论 -
35、二叉树的深度
题目:输入一棵二叉树的根节点,从该数的深度。即从根节点到叶节点依次经过的节点形成树的一条路径,最长路径的长度即为树的深度。解法:递归即可。注意:求二叉树的深度 为一个基本内容,在判断平衡二叉树或其他场合中经常用到。代码: int TreeDepth(TreeNode* pRoot) { if(pRoot==NULL) return 0; ...原创 2018-03-31 09:27:38 · 168 阅读 · 0 评论 -
34、数字在排序数组中出现的次数t
题目:统计一个数字在排序数组中出现的次数。解法:1、先求该数字出现的最左边位置。2、再求该数字出现的最右边位置。3、若该数字未出现,则会出现left在right右边。且相邻的情况。最后结果仍然为right-left+1 =0代码: int GetNumberOfK(vector<int> data ,int k) { if(data.size()==0||data...原创 2018-03-31 09:23:44 · 106 阅读 · 0 评论 -
33、两个链表的第一个公共结点
题目:输入两个链表,找出它们的第一个公共结点。解法:提供两种解法,都为o(m+n)的时间复杂度。前提:因为为普通链表,若两个链表有交点,从该交点开始,后面的节点都是公共的。即有交点的话,两条链表形成Y形, 而不是X形。(一)假设链表1为a-b-c-d-e-NULL, 链表2为f-g-e-NULL.分别遍历两个新的组合遍历(链表1+链表2 : a-b - c - d - e - NULL- f...原创 2018-03-30 15:50:14 · 76 阅读 · 0 评论 -
32、数组中的逆序对
题目:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对,输入一个数组,求出这个数组中的逆序对的总数P。对将P对1000000007取模的结果输出。对于50%的数据,size<=10^4对于75%的数据,size<=10^5对于100%的数据,size<=2*10^5解法:1、实质就是一个归并排序的过程2、在归并排序的过程中的merge部分,假设相邻的...原创 2018-03-30 11:26:54 · 92 阅读 · 0 评论 -
31、第一次只出现一次的字符
题目:在一个字符串(1<= 字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置。解法:1、利用一个数组实现哈希表的功能。2、在C++中 ASCII码 长度一共有256 ,因此用256大小的数组即可。3、在JAVA中 ASCII 为65536 ,要用对应大小的数组。代码如下: int FirstNotRepeatingChar(string st...原创 2018-03-30 10:10:48 · 92 阅读 · 0 评论 -
30、丑数
题目:求按从小到大顺序的第N个丑数。丑数:只包含因子2,3,5的整数称作丑数,把1当做第一个丑数。解法:1、假设数组中已有排好序的丑数,把已有的当前最大丑数记作M。2、接下来的一个丑数必然是前面某一个丑数乘以2、3或者5的结果。3、将前面所有丑数全部乘以2,能获得若干个小于或等于M的结果,这些已在排好序的数列中,还会出现若干个大于M的结果,我们把第一个大于M的结果记作M2。后面的结果都会大于M2,...原创 2018-03-30 09:58:17 · 136 阅读 · 0 评论 -
5、两个栈实现队列的push/pop
题目:用两个栈实现一个队列,完成队列的Push 和pop操。队列中的元素为int类型。解法:1、利用两个栈实现,分别记为stack1,stack2.2、队列的push操作:有新元素node进队列时候,让stack1.push(node)。3、队列的pop操作:将所有stack1的元素倒入到stack2中,stack2的top元素即为出队列的元素。 在stack1倒入stack2的操作中,需要...原创 2018-03-26 16:25:36 · 275 阅读 · 0 评论