剑指offer
雪沫沫
程序代码是个很神奇的东西,我不知道我会在这条路上走多久,但是和他打交道的每一秒我都是开心的,付出努力的。
展开
-
【每日一题】查找一个字符串中第一个只出现两次的字符
题目:查找一个字符串中第一个只出现两次的字符。比如:“abcdefabcdefabc”中第一个只出现两次为‘d’,要求时间复杂度为O(N),空间复杂度为O(1) 解决方法:可以使用哈希表统计每个字符出现的次数。因为字符只有256种可能,所以我们可以申请一个256大小的数组来统计每个字符出现的次数(以空间换时间),统计完后,我们以原数组的元素值为下表,访问统计数组,直到遇到第一个访问数组元素值为2的元原创 2017-07-20 12:57:06 · 4157 阅读 · 0 评论 -
实现一颗二叉树的层序遍历【每日一题】
题目:层序遍历二叉树给定一棵二叉树,要求层序遍历该二叉树,即从上到下按层次访问该树,每一层单独输出一行,每一层要求访问的顺序为从左到右。我们在遍历的过程中将该层节点的孩子节点压入一个队列,这样就可以实现从上到下一层一层地遍历该二叉树。 初始时,根结点入队列。 然后,while循环判断队列不空时,弹出一个结点,访问它,并把它的所有孩子结点入队列。template<class T>struct B原创 2017-07-21 13:31:56 · 377 阅读 · 0 评论 -
求数组中出现次数超过一半的字符【每日一题】
题目:数组中有一个数字出现的次数超过了数组长度的一半,找出这个字符。 解决方法: 方法1.首先我们想到如果是一个排序好的数组,那么我们只需要遍历一次数组,统计好每个数字出现的次数,如果大于数组长度的一半就输出这个数字。或者只需要直接输出array[N/2]的值即可。 (1)如果说数字只有0-9的话可以考虑设计一个Hash table,遍历一次就能知道每个数字出现的次数。但是数字原创 2017-07-22 12:39:42 · 847 阅读 · 0 评论 -
链表翻转(升级版)【每日一题】
题目:链表翻转。给出一个链表和一个数k,比如链表 1→2→3→4→5→6,k=2,翻转后2→1→4→3→6→5,若k=3, 翻转后3→2→1→6→5→4,若k=4,翻转后4→3→2→1→5→6, 用程序实现Node* RotateList(Node* list, size_t k)。 解决方法:思路和链表翻转一样是将该节点原来指向下一个节点的指针指向该节点的前一个节点,最后得到的新链表的头节原创 2017-07-23 13:03:33 · 253 阅读 · 0 评论 -
求二叉树的高度/销毁一颗二叉树【每日一题】
template<class T>struct BinaryTreeNode{ BinaryTreeNode(const T& data) :_data(data) ,_pLeft(NULL) ,_pRight(NULL) {} T _data; BinaryTreeNode<T>* _pLeft; Binar原创 2017-07-23 13:10:40 · 324 阅读 · 0 评论 -
二叉树三种遍历非递归实现【每日一题】
前序遍历: 根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;当访问其左子树时,再访问它的右子树。因此其处理过程如下: 对于任一结点P: 1)访问结点P,并将结点P入栈; 2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操原创 2017-07-28 16:04:38 · 524 阅读 · 0 评论 -
求一颗二叉树的镜像 【每日一题】
题目: 求一颗二叉树的镜像 解决方法: 创建一个树以后,交换每个节点的左右孩子//递归 void _GetBinaryMirror(Node* pRoot) { if(pRoot) { std::swap(pRoot->_pLeft ,pRoot->_pRight ); _GetBinaryMirr原创 2017-07-28 16:10:00 · 369 阅读 · 0 评论 -
判断一棵树是否是完全二叉树【每日一题】
完全二叉树的定义:对二叉树按照从上到下、从左到右的层次遍历,应该满足一下两条要求: ●某节点没有左孩子,则一定无右孩子 ●若某节点缺左或右孩子,则其所有后继一定无孩子 不满足上述任何一条,均不为完全二叉树。题目:判断一棵树是否是完全二叉树 解决方法:在层序遍历的过程中,找到第一个非满节。满节点指的是同时拥有左右孩子的节点。在找到第一个非满节点之后,剩下的节点不应该有孩子节点;如果有,那么该二原创 2017-07-28 17:10:55 · 626 阅读 · 0 评论 -
求二叉树叶子节点的个数和第k层的节点个数【每日一题】
1.求二叉树中叶子节点的个数 (1)如果二叉树为空,返回0 ; (2)如果二叉树不为空且左右子树为空,返回1; (3)如果二叉树不为空,且左右子树不同时为空,返回左子树中叶子节点个数加上右子树中叶子节点个数 。 2.求二叉树中第k层的节点个数 (1)若树为空或k小于1或k大于树的高度,则返回0; (2)若k=1,则表示第一层即为根节点个数,即返回1; (3)如果不是上两种情况,则返原创 2017-07-22 12:01:07 · 671 阅读 · 0 评论 -
计算阶乘结果中0的个数【每日一题】
题目:给定一个整数N,那么N的阶乘N!末尾有多少个0呢? 例如:N=10,N!=3 628 800,N!的末尾有两个0解决方法: 两个大数字相乘都可以拆分多个质数相乘,而质数相乘结果为0的只有2*5。那么两个数相乘尾数为0的个数其实就是依赖2和5的因子个数。又因为每两个连续数字就会有一个2,个数很充足所以只需要关心5因子的个数就行了。 那么怎么计算n!中5因子的个数呢? 把5的倍数都找出来,原创 2017-07-21 13:27:10 · 1395 阅读 · 0 评论 -
判断元素出栈、入栈顺序的合法性【每日一题】
题目:元素出栈、入栈顺序的合法性。如:入栈的序列(1,2,3,4,5),出栈序列为(4,5,3,2,1),则合法。入栈的序列(1,2,3,4,5),出栈序列为(4,5,2,3,1),则不合法。 解决方法:很直观的一种想法,建立一个辅助栈,把输入的第一个序列中的数字一次压入该辅助栈,并按照第二个序列的顺序从该栈中弹出数字。遍历出栈顺序中的元素,有两种情况 : (1)如果元素是栈顶的元素,则pop出原创 2017-07-20 13:54:04 · 408 阅读 · 0 评论 -
整数二进制位中1的个数【每日一题】
题目:计算一个整数二进制位中1的个数。要求效率尽可能的高。 且能正确求正数和负数的二进制中1的个数。//二进制中1的个数int CountOf1One(int num){ //但是如果不知道是多少位的机器,冒然给出的32会让人很费解 //所以修改如下 int count = 0; int i = 1; while(i<=32) {原创 2017-07-20 13:52:01 · 220 阅读 · 0 评论 -
【每日一题】实现一个栈Stack,要求实现Push(出栈)、Pop(入栈)、 Min(返回最小值的操作)的时间复杂度为O(1)
题目:实现一个栈Stack,要求实现Push(出栈)、Pop(入栈)、 Min(返回最小值的操作)的时间复杂度为O(1) 解决方法:使用两个栈_data和_min,_min做为辅助栈(每次压入_min的都是_data的最小值)。元素x入栈时,将x和_min栈顶元素做比较,如果x小于等于_min.top(),将x分别push到_data和_min,否则x只push到_data;元素出栈时,将_dat原创 2017-07-20 12:23:04 · 1698 阅读 · 0 评论 -
替换空格【每日一题】
题目:实现一个函数,要求吧字符串中的所有空格替换成“%20”。例如 “hello world ” ——> ”hello%20world%20” 以前一直觉得做这种题目没什么意义,直到前两天学了网络编程才知道这种题目的意义非比寻常。 在网络编程中,如果URL参数中含有特殊的字符,如空格、’#’等,导致服务器端无法识别时,就把这些特殊的字符转换成可以识别的字符。规则:%加上十六进制的ascii原创 2017-07-18 12:23:16 · 227 阅读 · 0 评论 -
栈与队列【每日一题】
1.两个栈实现一个队列: 思路一、s1是入栈的,s2是出栈的 入队列:直接压到s1里 出队列:先把s1中的元素全部压到s2中,弹出s2中的栈顶元素; 再把s2的所有元素压回s1中 思路二、s1是入栈的,s2是出栈的 入队列:如果s1为空,把s2中所有元素压到s1中;否则直接压入s1 出队列原创 2017-07-18 12:20:28 · 202 阅读 · 0 评论 -
复杂链表的复制【每日一题】
所谓复杂链表是指:节点域中除了有数据域和指向下一个节点的指针,还有一个指向任意节点的指针 链表结构:struct ComplexList{ DataType _data; ComplexList* _pNext; ComplexList* _pRadom;}ComplexList*, pComplexList; 在不使用辅助空间的情况下实现O(n)的时间效率,解决方法原创 2017-07-17 15:00:13 · 174 阅读 · 0 评论 -
删除一个无头单链表的非尾节点【每日一题】
1、删除一个无头单链表的非尾节点: 分析:既然是一个无头链表,那么我们就不能通过直接访问这种形式进行删除。找不到上一个,那么就找下一个,让tmp保存node后节点的信息,然后让改动node的值,让node指向tmp的下一个,此时删除tmp,也顺利完成题目的要求。void DelNoHeadNotTail(PNode* pHead , int pos){ if(NULL != pHead原创 2017-07-17 12:23:16 · 607 阅读 · 0 评论 -
链表相交问题【每日一题】
1.判断两个链表是否相交,若相交,求交点。(假设链表不带环) 两个链表均不含有环,链表相交如下图 解法一、直接法 直接判断第一个链表的每个结点是否在第二个链表中,时间复杂度为O(len1*len2),耗时很大。解法二、利用计数 如果两个链表相交,则两个链表就会有共同的结点;而结点地址又是结点唯一标识。因而判断两个链表中是否存在地址一致的节点,就可以知道是否相交了。可以对第一 个链表原创 2017-07-16 22:49:08 · 266 阅读 · 0 评论 -
类的三种特殊设计【每日一题】
1.设计一个类不能被继承 。 解法一、将该类的构造函数设为私有函数 在C++中子类的构造函数会自动调用父类的构造函数,子类的析构函数也会自动调用父类的析构函数,要想一个类不能被继承,我们只要把它的构造函数和析构函数都定义为私有函数,那么当一个类试图从它那继承的时候,必然会由于调用构造函数、析构函数而导致编译错误。那么既然这个类的构造和析构函数都是私有的,我们就必须通过定义公有的静态函数来创建和释原创 2017-07-16 22:18:18 · 237 阅读 · 0 评论 -
链表带环问题【每日一题】
1.如何判断是否有环? 与返回链表倒数第k个节点的问题类似,定义两个结点指针,一个走的快,一个走的慢,那么当快的那个指针追上慢的指针时,说明链表带环。2.如何计算环的长度? 从第一次相遇(超一圈)时开始计数,第二次相遇时停止计数,返回的这个计数即为环的长度。3.如何判断环的入口点:碰撞点到连接点的距离等于头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接点。上述是一个简原创 2017-07-16 18:23:13 · 296 阅读 · 0 评论 -
二维数组中的查找【每日一题】
题目:一个m*n的矩阵,从左到右从上到下都是递增的,给一个数x, 判断x是否在矩阵中。要求效率尽可能的高。 解决方法:从二维数组的右上角或者左下角开始找起, 如果右上角元素大于关键字,说明关键字不在右上角元素所在的列,因此剔除该列; 如果右上角元素小于关键字,说明关键字不在右上角元素所在的行,因此剔除该行; 如果右上角元素等于关键字,则查找成功; 如果右上角所在行与列都被剔除,则说明关键原创 2017-07-29 12:00:16 · 2550 阅读 · 0 评论