剑指Offer
本专栏用于实现和讲解《剑指Offer》里面的大部分题目,并使用通俗易懂方式进行讲解。里面也包含了博主对部分题目的理解和看法,也对部分题目添加了一些新的解法,希望能够帮助大家一起学习,交流......
Jeaten
学习使你我快乐
展开
-
连续子数组的最大和 — C++实现
题目描述HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)牛客网题目链接解题思路1代码实现class Solut原创 2020-09-23 14:48:47 · 818 阅读 · 0 评论 -
数据流中的中位数 — C++实现
题目描述如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。解题思路代码实现...原创 2020-09-22 19:09:51 · 470 阅读 · 0 评论 -
最小的k个数 — C++实现
题目描述输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。牛客网题目链接解题思路代码实现原创 2020-09-22 15:49:00 · 815 阅读 · 0 评论 -
数组中出现次数超过一半的数字 — C++实现
题目描述数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。牛客网题目链接解题思路数组中有一个数字出现的次数超过数组长度的一半,意味着这个数出现的次数比其他数字出现的次数的总和还要多,为解决这个问题,我们需要保存两个值:数组中的一个数字、该数字出现的次数,操作为:我们遍历到下一个数字的时候,如果下一个数字和我们之前保存的数字相同,则次数+1原创 2020-09-22 08:57:37 · 931 阅读 · 0 评论 -
字符串的排列 — C++实现
题目描述输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则按字典序打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。输入描述:输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。牛客网题目链接解题思路代码实现using namespace std;class Solution {public: vector<string> Permutation(string str) {原创 2020-09-21 23:17:17 · 726 阅读 · 0 评论 -
序列化二叉树 — C++实现
题目描述请实现两个函数,分别用来序列化和反序列化二叉树二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。例如,我们可以把一个只有根节点为1的二叉树序列化为"1,",然后通过自己原创 2020-09-11 22:15:58 · 345 阅读 · 0 评论 -
二叉搜索树与双向链表的几种解法 — C++实现
题目描述输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。解题思路代码实现原创 2020-09-09 10:33:43 · 200 阅读 · 0 评论 -
复杂链表的复制的几种解法 — C+++实现
题目描述输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)解题思路代码实现...原创 2020-09-08 11:08:04 · 365 阅读 · 0 评论 -
二叉树中和为某一值的路径 — C++实现
题目描述输入一颗二叉树的根节点和一个整数,按字典序打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。牛客网题目链接解题思路首先,只有遍历到叶子结点的路径才称之路径。因此,如果不是叶子结点就要一直遍历到叶子结点才能判断。为此,我们应将之前遍历到的路径和路径的和保存起来,当遍历到的结点为叶子结点且和为预期值的时候将整条路径输出。如果为叶子结点和与预期值不一样,则应将叶子结点在路径中删除,然后回退继续查找,直到所有路径都被遍历为止。代码原创 2020-09-07 11:25:08 · 287 阅读 · 0 评论 -
二叉搜索树的后序遍历序列 — C++实现
题目描述输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回true,否则返回false。假设输入的数组的任意两个数字都互不相同。牛客网题目链接解题思路代码实现...原创 2020-09-07 10:21:50 · 355 阅读 · 0 评论 -
按之字顺序打印二叉树 — C++实现
题目描述请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。牛客网题目链接解题思路可参考分行从上到下打印二叉树,可以隔行将顺序的结果逆序就行。或者一行用栈,另一行用队列来轮着存储。代码实现/*struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x)原创 2020-09-04 22:58:22 · 193 阅读 · 0 评论 -
分行从上到下打印二叉树 — C++实现
题目描述从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。牛客网题目链接解题思路与从上到下打印二叉树一样,都是先存在队列里,然后从队列里取出。只不过这里要区分每一层,因此我们在需要记住每一层有多少个元素,然后在每一层元素数量达到后切换下一层。代码实现class Solution {public: vector<vector<int> > Print(TreeNode* pRoot) { vector <vector <原创 2020-09-04 17:18:23 · 255 阅读 · 0 评论 -
从上往下打印二叉树 — C++实现
题目描述从上往下打印出二叉树的每个节点,同层节点从左至右打印。牛客网题目链接解题思路此题属于队列的应用,具体解题过程为:遇到根节点,先输出如果其有左右子结点,则将左右子结点存在队列中(置于队尾)再从队列中按序取出结点,并进行相同的操作,直至队列为空位置代码实现class Solution {public: vector<int> PrintFromTopToBottom(TreeNode* root) { vector <int>res原创 2020-09-04 15:08:09 · 260 阅读 · 0 评论 -
栈的压入、弹出序列 — C++实现
题目描述输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)解题思路代码实现...原创 2020-09-04 14:34:34 · 433 阅读 · 0 评论 -
包含min函数的栈 — C++实现
题目描述定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。牛客网题目链接解题思路构造一个和栈容量一致缓存栈,用于存储存储当前栈的最小值,具体操作过程为:入栈时数据直接入栈,缓存栈则入当前的最小值出栈时数据栈和缓存栈都出栈代码实现使用栈的版本class Solution {public: void push(int value) { data.push(value); if(cahe.empty原创 2020-09-04 09:58:11 · 221 阅读 · 0 评论 -
顺时针打印矩阵 — C++实现
题目描述输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.牛客网题目链接解题思路代码实现...原创 2020-09-04 09:12:43 · 337 阅读 · 0 评论 -
对称的二叉树 — C++实现
题目描述请实现一个函数,用来判断一棵二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。牛客网题目链接解题思路对称二叉树,即左右两边的数是对称的,因此我们可以从左右两边同时开始判断,如果遇到左边和右边不相等的情况,则不相等;一直到遍历结束,都没有不相等情况,则相等。即:左子树和右子树相等,右子树和左子树相等。代码实现/*struct TreeNode { int val; struct TreeNode *left; struct Tre原创 2020-09-02 21:56:52 · 444 阅读 · 0 评论 -
二叉树的镜像 — C++实现
题目描述操作给定的二叉树,将其变换为源二叉树的镜像。源二叉树和镜像二叉树的结构示意如下: 源二叉树 8 / \ 6 10 / \ / \ 5 7 9 11 镜像二叉树 8 / \ 10 6 / \ / \ 11 9 7 5解题思路代码实现...原创 2020-09-02 21:09:17 · 462 阅读 · 1 评论 -
树的子结构 — C++实现
题目描述输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)牛客网题目链接解题思路对于两颗树A和B,要判断B是否为A的子树,则其首先应满足根节点相同,然后再去比较;如果根节点不同,再用A的左子树与B相比,不满足条件的话再用A的右子树与B相比,还不满足则B不在A中。对于具体的比较,首先比较根节点,再比较左子树和右子树,当都能够满足的条件的话我们便可以认为B在A中。因此,我们可以使用递归的代码来实现。代码实现/*struct TreeNode { in原创 2020-09-02 17:16:47 · 268 阅读 · 0 评论 -
合并两个排序的链表 — C++实现
题目描述输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。牛客网题目链接求解思路给出两个链表,我们需要先比较两个结点的头结点,将小的结点保存,然后将这个结点后面的链表与另一个链表继续比较,进行同样的处理 — 典型的递归。同时需要注意:如果有其中一个链表为空,则返回另一链表代码实现class Solution {public: ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {原创 2020-09-02 14:31:36 · 199 阅读 · 0 评论 -
反转链表的几种解法 — C++实现
题目描述输入一个链表,反转链表后,输出新链表的表头。牛客网题目链接解题思路1使用额外空间,然后采用头插法将遍历到的结点插入到新建立链表的头部,将原链表的尾结点作为新链表的头结点即可,这种方法消耗的存储空间较大,新建了一个和原来链表一样大小的链表,不推荐。代码实现/*struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { }};*/class Solutio原创 2020-09-02 11:45:44 · 446 阅读 · 0 评论 -
链表中环的入口结点 — C++实现
题目描述给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。牛客网题目链接解题思路代码实现原创 2020-09-01 10:45:34 · 305 阅读 · 0 评论 -
链表中倒数第k个结点 — C++实现
题目描述输入一个链表,输出该链表中倒数第k个结点。牛客网题目链接解题思路直接思路是遍历链表,遍历的时候压栈,遍历完后出栈,倒数出k个就行。但这样肯定是拿不到Offer的。可以这么做,拿两个指针从头遍历,让一个先走k-1步,然后两个指针再一起走,当先走的指针遍历到尾结点时,后走的那个即为所求。有几个点需要注意:输入空链表的处理k为0的情况k大于链表的长度代码实现class Solution {public: ListNode* FindKthToTail(ListNode*原创 2020-08-30 23:32:31 · 307 阅读 · 0 评论 -
调整数组顺序使奇数位于偶数前 — C++实现
题目描述输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。牛客网题目链接解题思路class Solution {public: void reOrderArray(vector<int> &array) { int s=0,e=array.size(); while(s<e){ if(!odd原创 2020-08-30 18:01:32 · 354 阅读 · 0 评论 -
表示数值的字符串 — C++实现
题目描述请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示数值。 但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。牛客网题目链接解题思路其实是科学计数法的判读,任何一个数都可以写成A[.[B]][e|EC]的形式:A为数值的整数部分,可无(0.xxx)B为紧跟着小数点的小数部分C为紧跟着e或E的指数部分因此,对于一个字符串是否表示数值的判断,我们可以原创 2020-08-30 15:21:29 · 302 阅读 · 0 评论 -
正则表达式匹配 — C++实现
题目描述请实现一个函数用来匹配包括’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配牛客网题目链接解题思路这是一个字符串匹配的问题,只是有一些特殊字符的干扰,出现.可以代替任何字符,出现*则可以消去一些字符,我们只需要关注*,因为出现.我们可以认为匹配上了。首先我们应从模式字符串里进行匹配原创 2020-08-30 12:03:31 · 1527 阅读 · 0 评论 -
删除链表中重复的结点 — C++实现
#include <iostream>using namespace std;void init();struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { }};ListNode *head,*ptr;class Solution {public: ListNode* deleteDuplication(原创 2020-08-21 17:36:49 · 1205 阅读 · 0 评论 -
打印从1到最大的n位数 — C++实现
题目描述输入数字n,按顺序打印出从1到最大的n位十进制数。比如输入3,则打印出1,2,3一直到最大的3位999。盆友们首先想到的是for循环挨个输出,但是这样的话会有n过大,位数过高而造成溢出的情况解题思路1:字符数组法我们使用字符串来模拟数字,这样的话不管多少位我们都可以解决:构造字符数组:先构造一个n位,每一位都为'0'的数组,每次最后一位+1,重复这一过程到溢出为此(如2位,加到100就会溢出,因此输出1 ~ 99)输出:前面有0的话不输出(如001,应输出1)#include原创 2020-08-20 00:46:08 · 532 阅读 · 0 评论 -
不用库函数实现计算一个数的n次方
题目描述给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。保证base和exponent不同时为0牛客网题目链接求解思路1常规解法,需要注意几个点即可:底数为0,不管多少次方都为0(一般底数不为0)指数为0,结果为1指数为负数,结果为正数次幂的倒数class Solution {public: double Power(double base, int exponent) { double res原创 2020-08-18 20:05:53 · 759 阅读 · 2 评论 -
求二进制中1的个数的几种解法
题目描述输入一个整数,输出该数32位二进制表示中1的个数。其中负数用补码表示。牛客网题目链接求解思路1我们可以设置一个无符号整数1,从低位往高位(1-32)一直移动,然后与整数对应位置的数字进行比较(与运算),来实现计算1的个数,代码如下:class Solution {public: int NumberOf1(int n) { int count=0; unsigned int flag=1; while(flag){原创 2020-08-18 17:23:24 · 277 阅读 · 0 评论 -
剪绳子的几种解法 — C++实现
文章目录题目描述求解思路1:求解代码求解思路2:求解代码题目描述求解思路1:求解代码求解思路2:求解代码原创 2020-08-18 14:17:49 · 1107 阅读 · 0 评论 -
矩阵中的路径 — 回溯法C++实现
题目描述请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。例如矩阵中包含一条字符串"bcced“的路径,但是矩阵中不包含”abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。牛客网题目链接求解思路试探法 — 回溯法:在矩阵中进行逐个试探,从给定字符串中的字符挨个匹原创 2020-08-16 16:21:26 · 290 阅读 · 0 评论 -
使用2个栈实现队列及其最大容量
文章目录前言实现思路2个栈实现队列的最大容量用2个栈实现队列的C++代码拓展—牛客网题目链接前言通过我们在数据结构中的学习(或者可以直接看博主的《数据结构专栏》),我们知道:栈是先进后出的数据结构队列是先进先出的数据结构即栈是逆序的,队列是顺序的,因此我们通过两个栈(逆序的逆序为顺序)可以实现队列实现思路利用2个栈stack1和stack2实现队列将元素压入到stack1用来模拟入队操作stack1压入完成后弹出并将stack1中所有元素压入到stack2(此时已经为顺序,且stac原创 2020-08-13 16:38:57 · 1355 阅读 · 0 评论 -
重建二叉树C++实现
题目描述输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。牛客网题目链接解题思路对于任何一个二叉树,给定先序和中序,或者后序和先序的遍历结果,均可以构造出整个而插入本题给定了先序和中序,则求解思路为:给定一个二叉树的先序遍历,第一个出现的结点为二叉树的根结点(我们计为N)则在中序遍历中,结点N左边的元素为原创 2020-08-13 11:30:13 · 326 阅读 · 0 评论 -
从尾到头打印链表及应用
题目描述输入一个链表,按链表从尾到头的顺序返回一个ArrayList。题目牛客网链接解题思路链表的遍历是从头节点开始的,而栈是先进后出的,因此我们可以将遍历到的数据先进行压栈操作,然后遍历完了之后我们进行出栈操作,则得到的结果就是我吗所需要的从尾到头打印链表的结果C++求解代码:/*** struct ListNode {* int val;* struct ListNode *next;* ListNode(int x) :*原创 2020-08-12 13:38:16 · 95 阅读 · 0 评论 -
替换空格的几种解法
题目描述请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。牛客网题目连接题目分析字符串存在数组中,一个空格替换后需要多出2个存储位置,我们加以分析,会有以下两种情况:case1:不在原来的字符串上替换如果原来的字符串的存储空间非常有限,我们需要另外开辟一个足够大的数组,将原来数组里的内容复制过来,并在遇到空格时换成指定字符,这样的话需要比较多的额外空间。为避免浪费更多的存储空间,我们原创 2020-08-10 16:44:21 · 1172 阅读 · 0 评论 -
二维数组中的查找的两种解法及C++实现
二维数组中的查找的两种解法及C++实现题目描述在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组,判断数组中是否含有该整数。例如下面二维数组每行递增、每列都递增。如果从这个数组中查找数字7,则返回true;如果查找数字5,则返回false1 2 8 92 4 9 124 7 10 136 8 11 15解法1:暴力法从数组中挨个扫描,如果找到返回true,否则返回false(只是为了对比,不建议)解原创 2020-08-10 01:52:13 · 567 阅读 · 0 评论 -
找出数组中重复的数字的两种解法及C++实现
找出数组中重复的数字在一个长度为n的数组里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复的几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出应该是重复的数字2或者3。解题思路1:哈希法由于数组里所有数字的范围为0~n-1,因此,我们可以使用数组里数字的值来进行计算:初始化一个大小为n的计数数组遍历数组,将计数数组下标为遍历到元素的值+1(如,遍历到1,计数数组的1号元素+原创 2020-08-08 20:13:14 · 5444 阅读 · 0 评论