剑指与编美
文章平均质量分 67
剑指offer和编程之美上的题,总结学习。
小地盘
这个作者很懒,什么都没留下…
展开
-
剑指offer 面试题43—n个骰子的点数
题目:把n个骰子扔在地上,所有骰子朝上一面的点数之和为S。输入n,打印出S的所有可能的值出现的概率。解法一:递归 玩过麻将的都知道,骰子一共6个面,每个面上都有一个点数,对应的数字是1到 6之间的一个数字。所以,n个骰子的点数和的最小值为n,最大值为6n。因此,一个直观的思路就是定义一个长度为6n-n的数组,和为S的点数出现的次数保存到数组第S-n个元素里。另外,我原创 2015-05-27 10:23:45 · 1080 阅读 · 0 评论 -
剑指offer 面试题36—数组中的逆序对
题目:在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。例如在数组{7,5,6,4}中一共存在5对逆序对,分别是(7,6),(7,5),(7,4),(6,4),(5,4)基本思想:解法一:O(n^2)最简单的想法就是遍历每一个元素,让其与后面的元素对比,如果大于则count++,但是这样的时间复原创 2015-05-12 09:05:49 · 1578 阅读 · 0 评论 -
剑指offer 面试题27—二叉搜索树与双向链表
题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表,要求不能创建任何新节点,只能调整树中结点指针的指向。最后输出排序后双向链表。基本思想:二叉树中每个节点都有两个指向子节点的指针。在双向链表中,每个节点也有两个指针,分别指向前一个节点和后一个节点。二叉搜索树中,左子节点的值总是小于父节点的值,右子节点的值总是大于父节点的值。在转换成双向链表时,原先指向原创 2015-05-11 22:19:56 · 1523 阅读 · 0 评论 -
剑指offer 面试题26—复杂链表的复制
struct ComplexListNode { int m_nValue; ComplexListNode* m_pNext; ComplexListNode* m_pSibling; }; 以下图为5个结点的复杂链表,实线表示m_pNext指针的指向,虚线表示m_pSibling指针的指向原创 2015-05-11 21:29:20 · 1053 阅读 · 0 评论 -
剑指offer 面试题6—重建二叉树
题目:输入某二叉树的前序遍历和中序遍历,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含有重复的数字。例如,前序遍历序列:{1,2,4,7,3,5,6,8},中序遍历序列:{4,7,2,1,5,3,8,6}则重建出的二叉树如下所示,并输出它的头结点1。基本思想:前序遍历:前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时原创 2015-05-11 15:54:30 · 1001 阅读 · 0 评论 -
剑指offer 面试题15—链表中倒数第k个节点
基本思想:解法一:O(n^2)先算出链表的长度n,然后倒数第k个结点就是顺序的第(n-k+1)个数,不过这样需要2次遍历链表,第一次统计出链表中节点的个数n,第二次就能找到倒数第k个节点。解法二:O(n)只需一次遍历。设定两个指针p1和p2,两个指针刚开始都指向链表的第一个结点,然后让p1指针先走(k-1)步,然后再让两个指针一起往后走,当p1指针指向链表最后一个结点的时候原创 2015-05-10 20:05:50 · 1079 阅读 · 4 评论 -
剑指offer 面试题16—反转链表
题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。基本思想:定义三个指针,分别指向当前遍历到的节点,它的前一个节点以及后一个节点。最后反转后链表的头结点,就是原始链表的尾节点。尾节点的next为NULL。 #include using namespace std; typedef int原创 2015-05-10 20:08:33 · 964 阅读 · 0 评论 -
剑指offer 面试题17—合并两个排序的链表
题目:输入两个递增排序的链表,合并这两个链表并使得新链表中的节点仍然是按照递增排序的。基本思想:当我们得到两个链表中值较小的头结点并把它连接到已经合并的链表之后,两个链表剩余的节点依然是排序的,因此合并的步骤和之前的而不周是一样的。这就是典型的递归的过程。 #include using namespace std; ty原创 2015-05-10 20:21:27 · 1076 阅读 · 0 评论 -
剑指offer 面试题18—树的子结构
题目:输入两颗二叉树A和B,判断B是不是A的子结构。基本思想:1. 在树A中找到和B的根节点的值一样的节点R;(递归遍历)2. 再判断树A中以R为根节点的子树是不是包含和树B一样的结构。(递归遍历)#include #include using namespace std;//二叉树结点定义typedef struct BiTreeNode{原创 2015-05-10 20:34:38 · 1000 阅读 · 0 评论 -
剑指offer 面试题19—二叉树的镜像
题目:完成一个函数,输入一个二叉树,该函数输出它的镜像。基本思想:先前序遍历这棵树的每个节点,如果遍历到的节点有子节点,就交换它的两个子节点,当交换完所有的非叶子节点的左右子节点之后,就得到了树的镜像。#include #include using namespace std;//二叉树结点定义typedef struct BiTree原创 2015-05-10 20:41:58 · 1290 阅读 · 10 评论 -
剑指offer 面试题23—从上往下打印二叉树
题目:从上往下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。基本思想:遍历不是先序、中序、后序中的一种。规律:每一次打印一个节点的时候,如果该节点有子节点,则把该节点的子节点放到一个队里的末尾。接下来到队列的头部取出最早进入队列的节点,重复前面的打印操作。#include #include using namespace std;//二叉树结点原创 2015-05-07 13:38:20 · 1149 阅读 · 0 评论 -
剑指offer 面试题25—二叉树中和为某一值的路径
题目:输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。基本思想:规律:遍历到某一节点时,将节点添加到路径中,并累加该节点的值。如果该节点为叶节点并且路径中节点值的和等于输入整数,打印路径节点序列。不是,则继续访问它的子节点。当前节点访问结束后,递归函数将自动回到原创 2015-05-07 13:54:37 · 1661 阅读 · 0 评论 -
剑指offer 面试题24—二叉搜索树的后序遍历序列
题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。假设输入的数组的任意两个数字都互不相同。例如数组{5,7,6,9,11,10,8},就是下述的二叉树的后序遍历。基本思想:后序遍历中,最后一个数字是树的根节点,数组中前面的数字可以分为两部分:第一部分是左子树节点的值,它们都比根节点的值小;第二部分是右子树节点的值,它们都比根节点的值大。{5,原创 2015-05-07 13:53:09 · 932 阅读 · 0 评论 -
剑指offer 面试题50—树中两个节点的最低公共祖先
#include #include #include using namespace std;typedef struct TreeNode { int data; struct TreeNode *lchild; struct TreeNode *rchild; }TreeNode,*BiTree; //按先序序列创建二叉树 int C原创 2015-05-07 19:23:15 · 4444 阅读 · 0 评论 -
剑指offer 面试题45—圆圈中最后剩下的数字(约瑟夫环)
题目:0,1,。。。。,n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈中删除第m个数字。求出这个圆圈里剩下的最后一个数字。解法一:list实现环形链表,每当迭代器扫描到链表末尾的时候,把跌倒器移到链表的头部。这样就相当于按照顺序在一个圆圈里遍历了。解法二:数学公式f(n,m)表示n个数字的序列中最后剩下的数字,只需要得到n-1个数字的序列中最后原创 2015-05-07 15:58:35 · 1166 阅读 · 0 评论 -
剑指offer 面试题44—扑克牌的顺子
题目:从扑克牌中随机抽5张牌, 判断是不是一个顺子,即这5张牌是不是连续的。2-10为数字本身,A为1,J为11,Q为12,K为13,而大小王可以看成任意数字。基本思想:数组存储5张牌值,0代表大小王。1.首先把数组排序,从小到大排序;2.统计数组中0的个数;3.统计排序之后的数组中相邻数字之间的空缺总数 如果空缺总数小于或者等于0的个数,那么空缺可以有足原创 2015-05-07 15:57:04 · 1015 阅读 · 2 评论 -
剑指offer 面试题39—二叉树的深度vs平衡二叉树判断
题目一:输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。输入:第一行输入有n,n表示结点数,结点号从1到n。根结点为1。 n 输出:输出一个整型,表示树的深度。样例输入:32 3-1 -1-1 -1样例输出:2题目二:输入一棵二叉树的根节点,判断该树是不是平原创 2015-05-06 14:15:18 · 1015 阅读 · 0 评论 -
剑指offer 面试题41—和为s的两个数字VS和为s的连续正数序列
题目1:输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得他们的和正好是s。如果有多对数字的和等于s,全部输出。题目2:输入一个正数s,打印所有的和为s的连续正数序列(至少含有两个数)。例如输入15,由于1+2+3+4+5 = 4+5+6 = 7+8 = 15,所以打印三个连续序列,即1-5, 4-6, 7-8。题目1基本思想:两指针分别指向数组最前和最后位置原创 2015-05-03 14:57:39 · 798 阅读 · 0 评论 -
剑指offer 面试题42—翻转单词顺序VS左旋转字符串
题目1:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。例如输入字符串"I am a student.",则输出"student. a am I"。题目2:字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。例如输入字符串"abcdefg"和数字2,左旋转2位得到的结果"cdefgab"。题目1基本思想:第一步:翻转句子中的所原创 2015-05-03 15:44:35 · 827 阅读 · 0 评论 -
剑指offer 面试题12—打印1到最大的n位数
题目:输入3,打印:1、2、3......998、999 解法一:求出最大的n位数,然后循环从1开始逐个打印。解答二:解答一中当n很大时,会溢出。大数问题,用字符串解决。申请长度为n+1的字符串,实际数字位数不够n位时,在字符串的前半部门补0。初始化全部为'0',然后每一次为字符串表示的数字加1,再打印出来。两件事:1,在字符串表达的数字上模拟加1,原创 2015-05-04 15:09:48 · 830 阅读 · 0 评论 -
剑指offer 面试题13—在O(1)时间删除链表节点
题目:给你一个单链表的表头,再给你其中某个结点的指针,要你删除这个结点,条件是你的程序必须在O(1)的时间内完成删除。基本思想:普通的删除方法,首先通过表头,找到待删除结点(设为B)的前一个结点(设为A),将A的指向改一下就行,然后删除掉B结点就行了。要删除的结点一定要delete掉。void DeleteNode_On(ListNode *pHead, ListNod原创 2015-05-04 17:16:12 · 1244 阅读 · 0 评论 -
剑指offer 面试题30—最小的k个数
题目:输入n个整数,找出其中最小的k个数,例如输入4,5,1,6,2,7,3,8这个8个数字,则最小的4个数字是1,2,3,4.基本思想:解法一:先排序再找K:O(nlgn)最简单的方法就是把它排序,然后找出前面的k个数字就是最小的k个数字,这种思路的时间复杂度是O(nlgn)解法二:partition函数:O(n)利用快速排序的partition函数来原创 2015-05-05 21:29:06 · 913 阅读 · 0 评论 -
剑指offer 面试题37—两个链表的第一个公共节点
题目:输入两个链表,找出他们的第一个公共节点。解法一:O(mn)在第一个链表上顺序遍历每个节点,每遍历到一个节点的时候,在第二个链表上顺序遍历每个节点,找到一样的节点,即为第一个公共节点。解法二:O(m+n)空间复杂度为O(m+n)。从两个链表尾部开始往前比较,最后一个相同的节点就是第一个公共节点。用栈思想,分别把两个链表的节点放入两个栈里,这样两个原创 2015-05-06 12:03:58 · 1091 阅读 · 0 评论 -
剑指offer 面试题33—把数组排成最小的数
题目:输入一个正整数数组,把数组里面的所有数字连接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3, 32, 321},则打印这三个数字能排成的最小数字321323。基本思想:两个数字m和n能拼接数字mn和nm。如果mn如对321和32,排序为32132#include using namespace std;const int g_MaxN原创 2015-05-06 09:32:55 · 944 阅读 · 0 评论 -
剑指offer 面试题35—第一个只出现一次的字符
题目:在字符串中找出第一个只出现一次的字符。如输如“abaccdeff”,则输出‘b’。解法一:O(n2)遍历法,也就是从头开始取字符串中的一个字符,将其与其后的所有字符比较,如果有相同的字符,那么就证明它不是只出现一次的字符。当第一次出现遍历完其后字符并且没有重复时,表明这个字符就是“第一个只出现一次的字符”。如果字符串有n个字符,每个字符可能与后面的O(n)个字符相比较,因原创 2015-05-02 21:08:43 · 835 阅读 · 1 评论 -
剑指offer 面试题38—数字在排序数组中出现的次数
题目:统计一个数字在排序数组中出现的次数。例如输入排序数组{1,2,3,3,3,3,4,5}和数字3,由于3在这个数组中出现了4次,因此输出4.解法一:O(n)顺序遍历解法二:O(logn)用二分查找,分别找出第一个3,和最后一个3的位置,然后计算个数。#include int GetFirstK(int* data,int length,int k,i原创 2015-05-02 22:06:19 · 951 阅读 · 0 评论 -
剑指offer 面试题40—数组中两个只出现一次的数字
题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度O(n),空间复杂度O(1)。基本思想:http://blog.csdn.net/wtyvhreal/article/details/44260321#include using namespace std;int Find1(int n)//从低位开始找第原创 2015-05-02 23:00:48 · 659 阅读 · 0 评论 -
剑指offer 面试题47—不用加减乘除做加法
题目:做加法不能用四则运算。基本思路:位运算,考虑二进制加法的过程,步骤一、A^B,能够得到没有进位的加法。步骤二、A&B,能够得到相加之后,能够进位的位置的信息。向左移动一位,就是两个二进制数相加之后的进位信息。所以,(A&B)步骤三、将前两步的结果相加。相加的过程就是步骤一和步骤二,直到不再产生进位为止。#include using namespace s原创 2015-05-02 23:21:28 · 810 阅读 · 0 评论 -
剑指offer 面试题28—字符串的排列
题目:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出有字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。#include void foo(char *a,char *m){ if(*m=='\0') { printf("%s\n",a); return; } else { for(原创 2015-05-03 14:30:10 · 855 阅读 · 0 评论 -
剑指offer 面试题32—从1到n整数中1出现的次数
题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。例如输入12,从1到12这些整数中包含1的数字有1,10,11,12。所以1一共出现了5次。解法一:O(nlogn)基本思想:累加1到n每个整数中1出现的次数。n个数,每个数有O(logn)位。#include using namespace std;int numberof1(int n)原创 2015-04-30 17:09:12 · 1093 阅读 · 0 评论 -
剑指offer 面试题29—数组中出现次数超过一半的数字
题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。解法一:先将数组排序,然后出现次数超过一半的数字就是a[n/2+1],时间复杂度O(nlgn)。解法二:O(n)基本思想:消除原理:在遍历数组的时候保存两个值:一个原创 2015-04-30 11:03:30 · 851 阅读 · 0 评论 -
剑指offer 面试题21.22—栈操作以及判断弹出序列
题目:1.定义栈数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中,调用min、push以及pop的时间复杂度都是O(1)。2.输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序, 序列 4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,原创 2015-04-30 09:56:35 · 817 阅读 · 2 评论 -
剑指offer 面试题20—顺时针打印矩阵
题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。例如:如果输入如下矩阵:1 2 3 45 6 7 89 10 11 1213原创 2015-04-29 19:25:44 · 733 阅读 · 0 评论 -
剑指offer 面试题14—调整数组顺序使奇数位于偶数前面
题目:输入一个整数数组,实现一个函数来调整该数组中数组的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。解法一:O(n^2)从头扫描数组,每碰到一个偶数,拿出这个数字,并把位于这个数字后面的所有数字往前挪动一位。挪完之后在数组的末尾有一个空位,这时把该偶数放入这个空位中。由于每碰到一个偶数就需要移动O(n)个数字,因此总的时间复杂度是O(n^2).原创 2015-04-29 19:05:17 · 885 阅读 · 0 评论 -
编程之美2.19—区间重合判断
题目:输入两个表示区间范围的整数[x,y]然后输入N个无序区间[x1,y1], [x2, y2], [x3, y3]...求解第一次输入的区间是否在N个无序区间组合成的大区间中。基本思想:先用区间的左边界值对目标区间进行排序O(nlogn),对排好序的区间进行合并O(n),对每次待查找的源区间,用二分查出其左右两边界点分别处于合并后的哪个源区间中O(logn),若属于同原创 2015-04-28 22:58:32 · 1126 阅读 · 0 评论 -
编程之美3.3—计算字符串的相似度
题目:许多程序会大量使用字符串。对于不同的字符串,我们希望能够有办法判断其相似程序。我们定义一套操作方法来把两个不相同的字符串变得相同,具体的操作方法为: 1.修改一个字符(如把“a”替换为“b”); 2.增加一个字符(如把“abdd”变为“aebdd”); 3.删除一个字符(如把“travelling”变为“traveling”);比如,对于“abcdefg”和“abc原创 2015-04-28 13:35:33 · 1135 阅读 · 0 评论 -
编程之美3.1—字符串移位包含问题
题目:给定两个字符串s1和s2,要求判定s2是否能够被s1做循环移位得到的字符串包含。解法一:O(N^2)对s1进行循环移位,在进行字符串包含的判断。//s1,s2int len = strlen(s1);for(i:len){ char t=s1[0]; for(j:len-1) s1[j]=s[j+1]; s1[len原创 2015-04-28 11:54:02 · 929 阅读 · 2 评论 -
编程之美2.18—数组分割
题目:有一个没有排序,元素个数为2N的正整数数组。要求把它分割为元素个数为N的两个数组,并使两个子数组的和最接近。基本思想:假设数组A[1..2N]所有元素的和是SUM。模仿动态规划解0-1背包问题的策略,令S(k, i)表示前k个元素中任意i个元素的和的集合。显然:S(k, 1) = {A[i] | 1S(k, k) = {A[1]+A[2]+…+A[k]}原创 2015-04-28 11:37:54 · 1065 阅读 · 0 评论 -
编程之美3.6—判断两个链表是否相交
解法一:判断第一个链表的每个节点是否在第二个链表中,O(M*N);解法二:对第一个链表的节点地址hash排序,建立hash表,然后对第二个链表的每个节点的地址查询hash表,如出现,相交时间复杂度O(M+N),空间复杂度O(M)。解法三:把第二个链表接在第一个链表后面,得到的链表有环,相交,否则,不相交。‘第二个链表的表头一定在环上,只需从第二个链表开始原创 2015-04-27 23:03:15 · 781 阅读 · 0 评论 -
编程之美2.12—快速寻找满足条件的两个数
题目:能否快速找出一个数组中的两个数字,让这两个数字之和等于一个给定的值M。解法一:穷举:O(N^2)解法二:先排序,再二分查找M-a[i],排序O(NlogN),每个数二分查找O(NlgoN)总的时间复杂度O(NlogN)解法三:hash表,给定一个数字,根据hash映射查找另一个数字是否在数组中,O(1).总的时间复杂度O(N),原创 2015-04-27 22:41:05 · 965 阅读 · 0 评论