剑指offer习题
小麦大大
写写代码纪录生活
展开
-
数据流中的中位数
题目描述如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。class Solution {public: Solution() { count = 0;...原创 2019-05-10 18:47:48 · 137 阅读 · 0 评论 -
左旋转字符串
1、题目2、思路先局部翻转,后整体翻转。举例:abcdefg先局部翻转为bagfedc,后整体翻转为cdefgab。#include <iostream>#include <string>using namespace std;class Solution {public: string LeftRotateString(strin...原创 2018-08-20 15:14:05 · 193 阅读 · 0 评论 -
翻转单词顺序
1、题目2、思路两次翻转,第一次翻转整个句子,第二次翻转每个单词(单词之间用逗号隔开)#include <iostream>#include <string>using namespace std;class Solution {public: string ReverseSentence(string str) { ...原创 2018-08-20 15:09:49 · 186 阅读 · 0 评论 -
第一个只出现一次的字符
1.题目2.思路空间换时间。建立一个哈希表,第一次扫描字符串时,统计每个字符的出现次数。第二次扫描字符串时,返回第一个只出现一次字符的位置。class Solution {public: int FirstNotRepeatingChar(string str) { // 特殊输入 if(str.size() == 0) retu...原创 2018-08-20 00:16:32 · 125 阅读 · 0 评论 -
输入一颗二叉树的根节点,求二叉树的深度
1、题目2、思路class Solution {public: int TreeDepth(TreeNode* pRoot) { if(pRoot == nullptr) return 0; int left = TreeDepth(pRoot->left); int right...原创 2018-08-17 01:44:39 · 1414 阅读 · 0 评论 -
二叉搜索树转双向链表
1、题目输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。思路struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; }class Solutio...原创 2018-08-17 01:37:55 · 167 阅读 · 0 评论 -
判断一个序列是否是二叉搜索树的后序遍历
1、题目输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。 举例:序列{5,7,6,9,11,10,8}是下图二叉搜索树的后序遍历结果。2、思路性质: 二叉排序树的性质:左子树上所有节点的值均小于它的根节点;右子树上所有节点的值均大于它的根节点。 二叉排序树后序遍历的性质:序列最后一...原创 2018-08-17 01:16:17 · 331 阅读 · 0 评论 -
二叉树中和为某一值的路径
1、题目输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径由结点和有向边组成,从根结点到叶节点。2、例子2.思路本题使用前序遍历的方式访问节点,使用二维向量result存储全部路径,使用一维向量tmp存储当前路径。遍历二叉树的过程:按前序遍历顺序访问每一个节点。访问每个结点时,将结点添加到路径向量tmp中。如果当前结点是叶子结点,则判断当前路径...原创 2018-08-17 00:46:59 · 103 阅读 · 0 评论 -
把二叉树打印成多行
1、题目从上到下按层打印二叉树,同一层结点从左至右输出,每一层输出一行。例如:下面二叉树的打印结果为: 2.思路本题目使用队列和两个变量作为辅助,利用队列的先进先出策略,按层遍历二叉树。队列保存将要打印的节点,一个变量表示当前层中还没有打印的节点数,一个节点表示下一层节点的数目。struct TreeNode { int val; struct Tree...原创 2018-08-17 00:28:24 · 153 阅读 · 0 评论 -
之字形打印二叉树
1.题目请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。 2.思路本题使用两个栈作为辅助容器。打印某一层节点时,把下一层的子节点保存到栈内。如果当前打印的是奇数层,则先保存左子树节点再保存右子树节点到第一个栈内;如果当前打印的是偶数层,则先保存右子树在保存左子树节点到第二个栈内。...原创 2018-08-17 00:27:26 · 298 阅读 · 0 评论 -
字符串的排列
1、题目输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。2、思路(递归)分两步求字符串的全排列:首先求所有可能出现在第一个位置的字符,即把第一个字符和后面所有的字符交换;然后固定第一个字符,求后面所有字符的全排列。class Solution {p...原创 2018-08-19 17:00:15 · 92 阅读 · 0 评论 -
从1到n整数中1出现的次数:O(logn)算法(思维发散)
1、题目从1到n,每增加1,weight就会加1,当weight加到9时,再加1又会回到0重新开始。那么weight从0-9的这种周期会出现多少次呢?这取决于n的高位是多少,看图: 以534为例,在从1增长到n的过程中,534的个位从0-9变化了53次,记为round。每一轮变化中,1在个位出现一次,所以一共出现了53次。 再来看weight的值。weight为4,大于0,说明...原创 2018-08-19 16:37:14 · 1083 阅读 · 0 评论 -
字符串转换为数字
1、 题目把字符串转换成整数2、思路1.功能测试正数/复数/02.边界值测试最大的正整数/最小的负整数(数据上下溢出)3.特殊输入测试空字符串“”的处理,返回0,设置非法输入 字符串只有符号位的处理,返回0,设置非法输入 输入的字符串中有非数字字符,返回0,设置非法输入class Solution {public: int StrToInt...原创 2018-08-20 15:24:03 · 699 阅读 · 0 评论 -
表示数值的字符串
1、题目描述请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串”+100”,”5e2”,”-123”,”3.1416”和”-1E-16”都表示数值。 但是”12e”,”1a3.14”,”1.2.3”,”+-5”和”12e+4.3”都不是。2、思路我们首先分析一下子可能是数值的字符串的格式 在数值之前可能有一个表示正负的’-‘或者’+’。 接下来是若干个...原创 2018-08-20 15:34:16 · 177 阅读 · 0 评论 -
数值的整数次方
题目描述:实现函数double Power(doublebase, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。解题思路:当指数为负数的时候:可以先对指数求绝对值,然后算出次方的结果之后再取倒数;当底数(base)是零且指数是负数的时候:通过全局代码或异常告诉调用者参数有误;0的0次方的时候:由于0的0次方在数学上是没有意义的,因...原创 2019-05-10 17:50:23 · 135 阅读 · 0 评论 -
剑指offer删除链表节点O(1)算法
题目描述:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。解题思路:(1)常规思路:在单向链表中删除一个结点,最常规的做法无疑是从链表的头结点开始,顺序遍历查找要删除的结点,并在链表中删除该结点。这种思路由于需要顺序查找,时间复杂度自然就是O(n)。(2)正确思路:我们可以很方便地得到要删除的结点的一下结点。因此,我们可以把下一个结点的内容复制到需要删除的结...原创 2019-05-05 15:19:08 · 189 阅读 · 0 评论 -
删除链表中重复的结点
题目描述在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5/*struct ListNode { int val; struct ListNode *next; ListNode(int x) : ...原创 2019-01-22 17:20:35 · 241 阅读 · 0 评论 -
链表中环的入口结点
题目描述给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。思路二:既然有环,那么我们自然会想到用两个指针,一个走的快,一个走的慢,这样肯定有重合的时候,这时候 快指针比慢指针多走了一个环 :第一步,找环中相汇点。分别用pNode1,pNode2指向链表头部,pNode1每次走一步,pNode2每次走二步,直到pNode1==pNode2找到在环中的相汇点。第...原创 2019-01-22 16:49:13 · 100 阅读 · 0 评论 -
数字在排序数组中出现的次数
1、题目2、思路利用二分查找法,查找元素k在排序数组中第一次出现的位置m及最后一次出现的位置n,m-n+1即为元素k再排序数组中出现的次数。二分查找法在数组中找到第一个k的思路:先拿数组中间元素mid和查找元素k比较,如果k < mid,则第一个k只可能出现在数组的前半段;如果k>mid,则第一个k只可能出现在数组的后半段;如果k=mid,则先判断中间元素是不是第一...原创 2018-08-25 16:43:15 · 167 阅读 · 0 评论 -
第一个只出现一次的字符
1.题目2.思路 空间换时间。建立一个Map,第一次扫描字符串时,统计每个字符的出现次数。第二次扫描字符串时,返回第一个只出现一次字符的位置。class Solution {public: void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) { // 特殊...原创 2018-08-25 16:34:32 · 140 阅读 · 0 评论 -
和为s的两个数字
1、题目2、思路首先定义两个指针,第一个指针p指向数组的第一个数字,第二个指针q指向数组的最后一个数字。如果p+q=s,则找到要找的数字;如果p+q #include <iostream> #include <vector> using namespace std; /* 输入一个递增排序的数组和一个数字s,在数组中查找两个...原创 2018-08-25 16:24:56 · 181 阅读 · 0 评论 -
和为s的连续正数序列
题目思路设置两个辅助变量small和big,small表示序列的最小值,big表示序列的最大值。如果sum(small ~ big) > s,则增大small的值。如果sum(small ~ big) < s ,则增大big的值。因为序列要求至少两个数字,所以small增加到(s+1)/2为止。 #include <iostream>#inc...原创 2018-08-25 16:21:45 · 155 阅读 · 0 评论 -
找出数组中任意重复的数字(不修改数组)
题目在一个长度为n+1的数组里的所有数字都在1~n的范围内,所以数组中至少有一个数字是重复的。请找出数组中任意一个重复的数字,但不能修改输入的数组。例如,如果输入长度为8的数组{2,3,5,4,3,2,6,7},那么对应的输出是重复的数字2或者3。思路借鉴二分查找的思想,将数字1~n拆分成1~m和m+1~n两部分,如果数字范围1~m中数字个数大于m,则重复数字在1~m中间,否则重复...原创 2018-08-27 19:41:22 · 497 阅读 · 0 评论 -
二维数组中的查找
1.题目在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数数组和一个整数,判断数组中是否含有该整数。 #思路 首先选取数组中右上角的数字。如果该数字等于要查找的数字,查找过程结束;如果该数字大于要查找的数组,剔除这个数字所在的列;如果该数字小于要查找的数字,剔除这个数字所在的行。也就是说如果要查找的数字不在数...原创 2018-08-27 18:33:51 · 130 阅读 · 0 评论 -
旋转数组的最小数字(二分查找)
1.题目旋转数组的最小数字:输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 注意:给出的所有元素都大于0,若数组大小为0,请返回0。2、简单法:class Solution { public: int minNumberInRotateArray...原创 2018-08-27 18:26:38 · 293 阅读 · 0 评论 -
调整数组顺序使奇数位于偶数前面
1.题目输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分。2.思路要求稳定性的解法: 借鉴冒泡排序思想,每次确定一个位置。class Solution { public: void reOrderArray(vector<int> &array...原创 2018-08-27 18:12:26 · 155 阅读 · 0 评论 -
不使用新变量,交换两个变量的值(思维发散)
题目不使用新变量,交换两个变量的值思路方法一:使用加减法操作,交换两个变量的值。 A = A+B B = A-B A = A-B方法二:使用异或运算,交换两个变量的值 A = A^B B = A^B A = A^B#include <iostream>using names...原创 2018-08-19 14:13:48 · 937 阅读 · 0 评论 -
不用加减乘除做加法(思维发散)
1、题目2、 思路第一步:不考虑进位对每一位相加(异或操作) 第二步:考虑进位(位与运算+左移) 第三步:第一步和第二步相加(重复执行前两步)#include &lt;iostream&gt;using namespace std;class Solution {public: int Add(int num1, int num2) { ...原创 2018-08-19 14:07:24 · 322 阅读 · 0 评论 -
二叉树的下一个节点
1、题目2、 思路如果节点有右子节点,则右子节点的最左节点是该节点的下一个节点。例如,寻找b的下一个节点的过程(b有右子节点e,e的左子节点是h,且h是e的最左节点,h是b的下一个节点) 如果节点无右子节点,但该节点是父节点的左子节点,则父节点是该节点的下一个节点。例如,寻找d的下一个节点的过程(d无右子节点,d是父节点b的左子节点,则b是de的下一个节点) 如果节点无右子节点...原创 2018-08-16 14:18:25 · 112 阅读 · 0 评论 -
重建二叉树
1、题目输入某二叉树的前序遍历和中序遍历的结果,重建二叉树2、思路前序遍历中,第一个数字是二叉树的根节点 中序遍历中,根节点的左侧是左子树的节点,根节点的右侧是右子树的节点。 返回值:指向二叉树节点的指针 函数参数:前序遍历结果vector,中序遍历结果vector struct TreeNode { int val; TreeNode *...原创 2018-08-16 14:03:37 · 151 阅读 · 0 评论 -
两个链表的第一个公共结点
1、题目输入两个链表,找出它们的第一个公共结点。2、例子如、链表一 1 2 3 6 7 链表二 4 5 6 7 它们的第一个公共子结点为6。思路第一次遍历两个链表得到两个链表的长度,以及两个链表长度的差值error;第二次遍历两个链表时,先在较长的链表上走error步,接着分别遍历两个链表,找到的第一个相同的节点即为第一个公共节点,时间复杂度为O(m+n)。比如在上...原创 2018-08-16 05:36:20 · 115 阅读 · 0 评论 -
合并两个单调递增的链表
1.题目输入两个单调递增的链表,输出两个链表合成后的链表(单调不减)。2.思路(递归)鲁棒性: 如果链表1是空链表,则直接输出链表2。 如果链表2是空链表,则直接输出链表1。递归思路:定义三个指针,指向链表1头结点的指针p1,指向链表2头结点的指针p2,指向合并后链表头节点的指针head。比较p1和p2的值,如果p1 < p2,那么head指向p1,...原创 2018-08-16 05:11:14 · 358 阅读 · 0 评论 -
反转链表
1、题目输入一个链表的头结点,首先反转链表后,然后输出链表的所有元素2、思路辅助指针:定义三个用于翻转链表的辅助指针和一个用于表示翻转链表头结点的指针,node指向当前节点、left指向当前节点的前一个节点、right指向当前节点的下一个节点、ReverseHead指向翻转链表的头结点。翻转链表过程:循环翻转链表,每次循环翻转一个结点。判断node是否是最后一个结点,如果是最后...原创 2018-08-16 04:54:07 · 154 阅读 · 0 评论 -
链表中倒数第k个节点
1、题目输入一个链表,输出该链表中倒数第k个结点。链表的尾节点是倒数第一个节点。2、思路两个指针遍历链表:第一个指针从链表的头节点走k-1步,第二个指针不动;从第k步开始,第二个指针也开始从链表的头节点开始遍历,直到第一个指针指向链表结尾。由于两个指针的距离保持k-1,当第一个指针到达链表的尾节点时,第二个指针指向倒数第k个节点。鲁棒性:1.输入k=0时,输出nullptr...原创 2018-08-16 04:23:37 · 446 阅读 · 0 评论 -
从尾到头打印链表
1.题目输入一个链表,从尾到头打印链表每个节点的值2.思路不改变链表结构的情况下,首先,遍历链表将链表结点值存入栈中;然后,从栈顶逐个输出结点的值到向量 struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x...原创 2018-08-16 04:16:38 · 118 阅读 · 0 评论 -
滑动窗口的最大值
1、题目2、思路利用C++中的双端队列保存有可能是滑动窗口最大值的下标,其中队首元素保存当前窗口最大值的下标。当滑动窗口改变时,更新队列。队列更新的规则:(1)新元素依次与队尾元素比较,如果队尾元素小于新元素,则删除队尾元素,直至队列中没有小于新元素的值。(2)更新队首元素,如果队首元素不在新滑动窗口中,则删除队首元素。(3)把每次滑动的数字的下标压入队列#include <...原创 2018-08-18 01:54:58 · 120 阅读 · 0 评论 -
用两个栈实现队列插入和删除操作
1、题目用两个栈实现队列的插入和删除操作2、思路图解class Solution{public: // 两个栈模拟对列插入 void push(int node) { stack1.push(node); } // 两个栈模拟对列删除 int pop() { // stack2相关 i...原创 2018-08-18 01:14:47 · 1050 阅读 · 0 评论 -
栈的压入弹出序列
1、题目输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为第一个序列的出栈序列。注意:假设压栈序列的全部数字均不相等。 例如: 序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:出栈序列和入栈序列相等)2、思路定义一个辅助栈和两个变量。把第一个...原创 2018-08-18 00:54:47 · 117 阅读 · 0 评论 -
包含min函数的栈
1.题目定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。在该栈中调用push、pop、top、min的时间复杂度都是o(1)。思路定义一个辅助栈,用于存放数据栈每次入栈时的最小元素,辅助栈的栈顶元素是数据栈内最小值。 举例:创建一个空数据栈和空辅助栈。 1.数据栈中压入3,辅助栈为空栈,最小值为3,辅助栈压入3 2.数据栈中压入4,4大于辅助栈的...原创 2018-08-18 00:36:18 · 122 阅读 · 0 评论 -
剑指offer--替换空格
一、题目题目描述 请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。二、代码块代码块语法遵循标准markdown代码,例如:class Solution {public: void replaceSpace(char *str,int length) {...翻译 2018-08-08 09:07:29 · 144 阅读 · 0 评论