剑指offer
啥都不会的小白
渡河
展开
-
一刷剑指offer(50)——树中两个结点的最低公共祖先
//GetLastCommonNode用来得到两个路径path1和path2的最后一个公共结点TreeNode* GetLastCommonNode(const list<TreeNode*>& path1,const list<TreeNode*>& path2){ list<TreeNode*>::const_iterator ...原创 2019-10-20 08:30:00 · 175 阅读 · 0 评论 -
一刷剑指offer(49)——把字符串转换成整数
enum Status {kValid=0,kInValid};int g_nStatus=kValid;long long StrToIntCore(const char* digit,bool minus){ long long num=0; while(*digit!='\0') { if(*digit>='0' && ...原创 2019-10-19 08:29:41 · 185 阅读 · 0 评论 -
一刷剑指offer(48)——不能被继承的类
题目:用C++设计一个不能被继承的类。解法一:从构造函数下手C++中字类的构造函数会自动调用父类的构造函数,子类的析构函数会自动调用父类的析构函数。要想一个类不被继承,只需把它的析构函数和构造函数定义为私有函数即可,这样当一个类试图继承时,必然会因为调用构造函数和析构函数而导致编译出错。如何得到这样的一个实例?定义公有的静态函数来创建和释放类的实例。class Sea...原创 2019-10-18 07:34:23 · 145 阅读 · 0 评论 -
一刷剑指offer(47)——不用加减乘除做加法
题目:写一个函数,求两个整数之和,要求在函数体内不得使用加减乘除四则运算符号。求两数之和四则运算不可用,也就是说,只能用位运算。分析一下十进制加法的步骤:1、各位相加不进位2、做进位3、将前面两个结果加起来转换成位运算:1、不考虑进位,0+0=0,1+1=0,0+1=1,1+0=1,显然为异或运算。2、只有1+1才会产生进位,可以想象成两个数先做位与运算,然后再...原创 2019-10-17 07:42:53 · 99 阅读 · 0 评论 -
一刷剑指offer(46)——求1+2+..+n
题目:求1+2+..+n,要求不能使用乘除法,for,while,if,else,switch,case等关键字以及条件判断语句(A?B:C)。通常的求法:循环与递归,但是这里已经限制了使用循环(for,while)和递归(if)。可以考虑使用别的方法来间接实现循环与递归。解法一:构造函数——实现循环循环就是让相同的代码执行n遍,这里可以先定义一个类型,接着创建n个该类型的实例...原创 2019-10-16 07:31:17 · 106 阅读 · 0 评论 -
一刷剑指offer(45)——圆圈中最后剩下的数字
题目:0,1,....,n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。例如:0-1-2-3-4-0这5个数字组成一个圆圈,假如每次删除第3个数字,即删除2,0,4,1,最后剩下3。解法一:环形链表模拟创建一共有n个结点,然后每次在这个链表中删除第m个结点。可用STL中std::list模拟环形链表,但由于std::...原创 2019-10-15 08:16:04 · 79 阅读 · 0 评论 -
一刷剑指offer(44)——扑克牌的顺子
题目:从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,k为13,大小王可看作任意数字。抽象:将5张牌看成由5个数字组成的数组。大小王不妨定义为0。如何判断5个数字是否连续?对数组进行排序。且当数组中出现不连续的空缺时,检查数组中0的个数,可用0去补空缺。步骤:1、数组排序2、统计0的个数3、统计排序...原创 2019-10-14 07:25:05 · 98 阅读 · 0 评论 -
一刷剑指offer(43)——n个骰子的点数
题目:把n个骰子扔在地上,所有骰子朝上的一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。骰子一共6个面,每个面上对应一个点数(1-6)。所以n个骰子点数和min=n,max=6n。n个骰子所有点数的排列数为6^n。要计算概率,即要先统计出每一个点数出现的次数,再除以6^n即可。解法一:递归1、将n个骰子分成两堆:1个 (n-1)个,单独骰子的点数+(n-...原创 2019-10-13 09:07:22 · 90 阅读 · 0 评论 -
一刷剑指offer(42)——翻转单词顺序VS左旋转字符串
题目:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入"I am a student.",则输出"student. a am I"。思路:分两步进行翻转:1、翻转句子中所有的字符,此时不但翻转了句子中单词的顺序,单词内字符顺序也被翻转了。2、翻转单词中字符的顺序//翻转整个句子void Reverse(ch...原创 2019-10-12 07:21:01 · 83 阅读 · 0 评论 -
一刷剑指offer(33)——把数组排成最小的数
题目:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3、32、321},则打印321323。最直接的做法:先求出这个数组中所有数字的全排列,然后把每个排列拼起来,最后求出拼起来的数字的最大值。另一种做法:确定新的排序顺序。也就是给出两个数字m、n,需要确定一个规则判断m、n谁放前,谁放后,而不仅仅是比较两个数字的大小。如果...原创 2019-10-03 09:14:39 · 76 阅读 · 0 评论 -
一刷剑指offer(32)——从1到n整数中1出现的次数
题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。例如输入12,从1到12这些整数里,包含1的数字有1,10,11,12,1一共出现5次。最直接的思路:直接累加每个整数1出现的次数。对于小于10的数,对10求余判断整数个位数是否为1;对于大于10的数,除以10再判断个位数是否为1。int NumberOf1(unsigned int n){ int n...原创 2019-10-02 09:05:19 · 101 阅读 · 0 评论 -
一刷剑指offer(31)——连续子数组的最大和
题目:输入一个整型数组,数组里有正数也有负数。数组中一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。例如输入数组{1,-2,3,10,-4,7,2,-5},和最大子数组为{3,10,-4,7,2},子数组和为18。最直观的方法就是枚举数组的所有子数组并求出它们的和。一个长度为n的数组,总共有n(n+1)/2个子数组。计算出所有子数组的和,最快也要O(n...原创 2019-10-01 07:47:21 · 102 阅读 · 0 评论 -
一刷剑指offer(30)——最小的k个数
题目:输入n个整数,找出其中最小的k个数。例如输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。最简单的思路:将输入的n个整数排序,排序之后位于最前面的k个数就是最小的k个数。时间复杂度O(nlogn)。另一种思路:基于快速排序Partition函数。基于数组的第k个数字来调整,使得比第k个数字小的所有数字都位于数组左边,比第k个数字大的所有数字都位于...原创 2019-09-30 08:48:51 · 80 阅读 · 0 评论 -
一刷剑指offer(29)——数组中出现次数超过一半的数字
题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。直接的思路就是先给数组进行排序,然后就能很容易地统计出每个数字出现的次数。但是这种思路并没有考虑到数组的特性:数组中有一个数字出现的次数超过了数组长度的一半。如果将这个数组排序,那么排序之后位于数组中间的数字一定就是那个出现次数超过数组长度一半的数字,即中位数。bool g_bInputInvalid=false...原创 2019-09-29 08:37:28 · 78 阅读 · 0 评论 -
一刷剑指offer(38)——数字在排序数组中出现的次数
题目:统计一个数字在排序数组中出现的次数。例如输入排序数组{1,2,3,3,3,3,4,5}和数字3,由于3在这个数组中出现了4次,因此输出4.最直接的做法:先用二分查找算法找到一个3,由于3可能出现多次,因此我们找到的3的左右两边可能都有3,于是在找到的3左右两边顺序扫描,分别找到第一个3和最后一个3。因为要查找的数字在长度为n的数组中有可能出现O(n)次,因此这种算法的效率和直接从头到...原创 2019-10-08 08:02:34 · 104 阅读 · 0 评论 -
一刷剑指offer(28)——字符串的排列
题目:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab,cba。求整个字符串的排列,可以看成两步:1、求所有可能出现在第一个位置的字符,即把第一个字符和后面所有的字符交换。2、固定第一个字符,求后面所有字符的排列,这时依然将后面的所有字符分成两部分:后面字符的第一个字符,以及...原创 2019-09-28 08:17:20 · 70 阅读 · 0 评论 -
一刷剑指offer(34)——丑数
题目:我们把只含因子2、3、5的数称作丑数。求按从小到大的顺序的第1500个丑数。例如6、8都是丑数,但14不是,因为它包含因子7。习惯上,我们把1当作第一个丑数。根据丑数的定义,丑数只能被2、3、5整数。判断一个数是否为丑数:如果能被2整除,那么把它连续除以2;如果能被3整除,那么把它连续除以3;如果能被5整除,那么把它连续除以5。最后结果为1,即为丑数。否则不是。bo...原创 2019-10-04 09:23:15 · 87 阅读 · 0 评论 -
一刷剑指offer(35)——第一个只出现一次的字符
题目:在字符串中找到第一个只出现一次的字符。如输入“abaccdeff”,输出'b'。最直观的做法:从头开始扫描这个字符串中每个字符。当访问到某个字符时,拿这个字符和后面的每个字符相比较,如果在后面没有发现重复的字符,则该字符为只出现一次字符。若字符串有n个字符,那么时间复杂度为O(n^2)。哈希表法:由于题目与字符出现的次数相关,因此需要统计每个字符在字符串中出现的次数。可以...原创 2019-10-05 08:48:26 · 80 阅读 · 0 评论 -
一刷剑指offer(36)——数组中的逆序对
题目:在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对总数。例如数组{7,5,6,4|中,存在5个逆序对:(7,6),(7,5),(7,4),(6,4),(5,4)。最直接的做法:顺序扫描整个数组,每扫描到一个数字,逐个比较该数字和它后面数字的大小。如果后面数字比它小,则这两个数字就组成了一个逆序对。假设数组中含有n个数字...原创 2019-10-06 09:13:57 · 64 阅读 · 0 评论 -
一刷剑指offer(37)——两个链表的第一个公共结点
题目:输入两个链表,找出它们的第一个公共结点。链表结点定义如下:struct ListNode{ int m_nKey; ListNode* m_pNext;};最直接的做法:在第一链表上顺序遍历每个结点,每遍历到一个结点时,在第二个链表上顺序遍历每个结点。如果在第二个链表上有一个结点和第一个链表上的结点一样,说明两个链表在这个结点上重合,于是找到它们的公...原创 2019-10-07 09:57:00 · 159 阅读 · 0 评论 -
一刷剑指offer(39)——二叉树的深度
题目:输入一颗二叉树的根结点,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。二叉树结点定义如下:struct BinaryTreeNode{ int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight;};递归:...原创 2019-10-09 07:20:10 · 119 阅读 · 0 评论 -
一刷剑指offer(40)——数组中只出现一次的数字
题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字,要求时间复杂度为O(n),空间复杂度为O(1)。例如输入{2,4,3,6,3,2,5,5},输出4和6。异或的性质:若A!=B,则A xor B=1;若A==B,则A xor B=0。即任意一个数字,异或它自己都为0。先不考虑数组中有两个只出现一次的数字,先考虑数组中仅有一个只出现...原创 2019-10-10 08:09:33 · 83 阅读 · 0 评论 -
一刷剑指offer(41)——和为s的两个数字VS和为s的连续正数序列
题目:输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得他们的和正好是s。如果有多对数字的和为s,输出任意一对即可。最直接的做法:双重循环依次尝试,时间复杂度O(n^2)。更好的方法:1、在数组中选择两个数字(不妨设两个指针,一个指向最小元素,一个指向最大元素),如果它们的和等于输入的s,就找到了两个数字;2、如果和小于s,由于已经排序,选择较小数字后面的数字,即第一...原创 2019-10-11 07:31:25 · 81 阅读 · 0 评论 -
一刷剑指offer笔记(7)——用两个栈实现队列
栈是一种非常常见的数据结构,不考虑排序,需要O(n)时间才能找到栈中最大或者最小的元素,入宫要在O(1)时间内得到栈的最大值或最小值,需要对栈做出特殊设计。栈与队列最明显的区别在于:栈是后进先出,队列是先进先出。题目:用两个栈实现一个队列。队列声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能。template...原创 2019-09-08 08:20:42 · 105 阅读 · 0 评论 -
一刷剑指offer(27)——二叉搜索树与双向链表
题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新结点,只能调整树中结点指针的指向。二叉树结点定义如下:struct BinaryTreeNode{ int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight;};二叉搜索树与双向链表转换...原创 2019-09-27 07:32:07 · 73 阅读 · 0 评论 -
一刷剑指offer(26)——复杂链表的复制
题目:请实现函数ComplexListNode* Clone(ComplexListNode* pHead),复制一个复杂链表。在复杂链表中,每个结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中的任意结点或者NULL。结点定义如下:struct ComplexListNode{ int m_nValue; ComplexList...原创 2019-09-26 08:23:00 · 78 阅读 · 0 评论 -
一刷剑指offer(25)——二叉树中和为某一值的路径
题目:输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。从树的根结点开始往下,一直到叶结点所经过的结点形成一条路径。二叉树结点定义为:struct BinaryTreeNode{ int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight;};由于路...原创 2019-09-25 08:32:08 · 81 阅读 · 0 评论 -
一刷剑指offer(12)——打印1到最大的n位数
题目:输入数字n,按顺序打印出从1到最大的n位十进制数。比如输入3,则打印出1、2、3....999这个题目貌似很简单,最直接的方法就是先求出最大的n位数,然后用一个循环从1开始逐个打印。但是要注意的是,当输入的n很大的时候,会产生溢出,需要考虑大数问题。怎么表示大数?字符串或者数组。1、字符串模仿数字加法因为数字最大是n位,因此字符串长度应为n+1位(结束符号'\0'),当实...原创 2019-09-13 08:56:29 · 118 阅读 · 0 评论 -
一刷剑指offer笔记(11)——数值的整数次方
题目:实现函数double Power(double base,int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。double Power(double base,int exponent){ double result=1.0; for(int i=1;i<=exponent;i++) re...原创 2019-09-12 08:40:34 · 94 阅读 · 0 评论 -
一刷剑指offer笔记(10)——二进制中1的个数
位运算是把数字用二进制表示之后,对每一位上0或者1的运算。位运算包括五种:与、或、异或、左移和右移。题目:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如把9表示成二进制是1001,有2位是1。因此输入9,输出2。一个最基本的思路:先判断整数二进制表示中最右边是不是1,接着把输入的整数右移一位,此时原来处于从右边数起的第二位被移到最右边了,再判断是不是1。这样每...原创 2019-09-11 08:23:47 · 91 阅读 · 0 评论 -
一刷剑指offer笔记(9)——Fibonacci数列
如果我们需要重复多次计算相同的问题,通常可以选择用递归或者循环两种不同的方法。递归是在一个函数内部调用这个函数自身,循环是通过设置计算的初始值及终止条件,在一个范围内重复运算。虽然递归比较简洁,但是由于函数调用是有时间和空间消耗的,每一次函数调用都需要在内存栈中分配空间以保存参数、返回地址及临时变量,如果超过栈的容量会导致调用栈溢出,而且往栈内压入数据和弹出数据都需要时间,因此效率比较低。...原创 2019-09-10 08:27:04 · 191 阅读 · 0 评论 -
一刷剑指offer笔记(8)——旋转数组的最小数字
题目1:对某公司所有员工年龄进行排序,可使用常量大小辅助空间。//题目解析://公司员工年龄有一个范围,这里设为0-99//数组timeOfAge用来统计每个年龄出现的次数//某个年龄出现了多少次就在数组ages里设置几次该年龄,相当于对ages排序void SortAges(int ages[],int length){ if(ages==NULL || length&l...原创 2019-09-09 09:26:49 · 75 阅读 · 0 评论 -
一刷剑指offer笔记(6)——重建二叉树
树:除了根结点之外每个结点只有一个父节点,根结点没有父结点。除了叶结点之外的每个结点都有一个或多个子结点,叶结点没有子结点。如果每个结点最多只能有两个子结点,则为二叉树。二叉树的遍历方式有四种:前序遍历(根-左-右)、中序遍历(左-根-右)、后序遍历(左-右-根)、层序遍历当左<=根<=右,为二叉搜索树当根结点值最大,为最大堆当根结点值最小,为最小堆当从...原创 2019-09-07 08:26:06 · 70 阅读 · 0 评论 -
一刷剑指offer笔记(5)——从尾到头打印链表
链表是一种动态数据结构,因为在创建链表时,无须知道链表的长度。当插入一个结点时,我们只需要为新结点分配内存,然后调整指针指向来确保新结点被链接到链表中。内存分配不是在创建链表时一次性完成,而是每添加一个结点就分配一次内存。由于没有闲置的内存,链表的空间效率高于数组。题目:输入一个链表的头结点,从尾到头反过来打印出每个结点的值。链表结点定义如下:struct ListNode{ ...原创 2019-09-06 07:25:21 · 84 阅读 · 0 评论 -
一刷剑指offer笔记(4)——替换空格
C/C++中每个字符串都以字符'\0'作为结尾,因此每个字符串中都有一个额外字符开销,否则会造成字符串的越界。需要注意的是字符串数组与指针的区别。如果两个字符串数组内容相同,他俩也不同,因为这俩数组的初始地址不同;但是指针无需分配内存存储字符串,只要指向内存地址即可。为了节省内存,C/C++把常量字符串放到单独的一个内存区域。当几个指针赋值给相同的常量字符串时,他们实际会指向相同的内存...原创 2019-09-05 09:34:31 · 77 阅读 · 0 评论 -
一刷剑指offer笔记(3)——二维数组中的查找
数组,占据一块连续内存并按照顺序存储数据的一种最简单的数据结构。数组的空间效率不好,经常会有空闲的区域没有得到充分利用。数组的时间效率较好,可以根据下标在O(1)时间读写任何元素。可以利用数组来实现简单哈希表O(1)查找:以数组下标作为哈希表的键值key,以数组中的每一个数字作为哈希表的值(value).值得注意的是,当数组作为函数的参数进行传递时,数组会自动退化为同类型的指针。...原创 2019-09-04 09:12:40 · 122 阅读 · 0 评论 -
一刷剑指offer笔记(2)——实现Singleton模式
题目:设计一个类,我们只能生成该类的一个实例Singleton模式是最简单的设计模式之一,它提供了创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一对象的方式,可以直接访问,不需要实例化该类的对象,毕竟只有一个实例。注意:1、单例类只能有一个实例2、单例类必须自己创建自己的唯一实例3、单例类...原创 2019-09-03 09:37:06 · 124 阅读 · 0 评论 -
一刷剑指offer(13)——在O(1)时间删除链表结点
题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。链表结点与函数定义如下:struct ListNode{ int m_nValue; ListNode* m_pNext;};void DeleteNode(ListNode** pListHead,ListNode* pToBeDeleted);在单向链表中删除一个结点,最常规的做法...原创 2019-09-14 08:18:51 · 65 阅读 · 0 评论 -
一刷剑指offer(14)——调整数组顺序使奇数位于偶数前面
题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。如果不考虑时间复杂度,最简单的思路就是从头扫描这个数组,每遇到一个偶数时,就将位于这个数字后面的所有数字往前挪一位,同时将该偶数放入数组末尾最后一个空位。由于每遇到一个偶数就需要移动O(n)个数字,因此总的时间复杂度是O(n^2)。法一:题目要求把奇数放在数组的前...原创 2019-09-15 08:37:20 · 68 阅读 · 0 评论 -
一刷剑指offer(24)——二叉搜索树的后序遍历序列
题目:输入一个整数数组,判断该数组是不是某二叉树的后序遍历结果。如果是,则返回true,否则返回false。假设输入的数组的任意两个数字互不相同。在后序遍历得到的序列中,最后一个数字是树的根结点。数组中前面的数字可以分为两部分:第一部分是左子树的结点,它们都比根结点小;第二部分是右子树的结点,它们都比根结点大。以数组{5,7,6,9,11,10,8}为例,后序遍历的结果的最后一个数字8...原创 2019-09-24 07:50:32 · 85 阅读 · 0 评论