
剑指offer
Johnnay_Song
流水不争先
展开
-
【38】面试题45:圆圈中最后剩下的数字
【1】题目题目:0,1,…,n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。【2】思路我们自己实现一个链表也不是很难的事情。如果面试官没有特殊要求,我们就可以用模板库中的std::list来模拟一个环形链表。由于std::list本身并不是一个环形结构,因此每当迭代器(Iterator)扫描到链表末尾的时候,我们要记得把迭代器移到链表的头部,这样就相当于按照顺序在一个圆圈里遍历了【3】代码// Test42.cpp : 此文件原创 2021-04-10 11:57:30 · 149 阅读 · 0 评论 -
【37】面试题44:扑克牌的顺子
【1】题目题目:从扑克牌中随机抽 5张牌,判断是不是一个顺子,即这 5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王可以看成任意数字。【2】思路首先把数组排序,再统计数组中0的个数,最后统计排序之后的数组中相邻数字之间的空缺总数。如果空缺的总数小于或者等于0的个数,那么这个数组就是连续的;反之则不连续。最后,我们还需要注意一点:如果数组中的非 0 数字重复出现,则该数组不是连续的。换成扑克牌的描述方式就是如果一副牌里含有对子,则不可能是顺子。【3】原创 2021-04-09 21:44:47 · 194 阅读 · 0 评论 -
【36】面试题43:n个骰子的点数
【1】题目题目:把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。【2】思路可以换一种思路来解决这个问题。我们可以考虑用两个数组来存储骰子点数的每一个总数出现的次数。在一次循环中,第一个数组中的第 n 个数字表示骰子和为n出现的次数。在下一循环中,我们加上一个新的骰子,此时和为 n 的骰子出现的次数应该等于上一次循环中骰子点数和为 n-1、n-2、n-3、n-4、n-5与 n-6的次数的总和,所以我们把另一个数组的第 n个数字设为前一个数组对应的第 n原创 2021-04-09 21:05:38 · 150 阅读 · 0 评论 -
【35】面试题42:翻转单词顺序 VS左旋转字符串
【1】题目题目一:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student.",则输出"student.a am I"【2】思路法,于是很快就可以跟面试官解释清楚解题思路:第一步翻转句子中所有的字符。比如翻转"I am a student."中所有的字符得到".tneduts a ma I",此时不但翻转了句子中单词的顺序,连单词内的字符顺序也被翻转了。第二步再翻转每个单词中字符的顺序,就得到了"stud原创 2021-04-09 11:55:03 · 162 阅读 · 0 评论 -
【34】面试题41:和为s的两个数字VS和为s的连续正数序列
【1】题目题目一:输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,输出任意一对即可。【2】思路我们先在数组中选择两个数字,如果它们的和等于输入的s,我们就找到了要找的两个数字。如果和小于s呢?我们希望两个数字的和再大一点。由于数组已经排好序了,我们可以考虑选择较小的数字后面的数字。因为排在后面的数字要大一些,那么两个数字的和也要大一些,就有可能等于输入的数字s了。同样,当两个数字的和大于输入的数字的时候,我们可以选择较大数字前面的数字,因为原创 2021-04-09 11:06:15 · 81 阅读 · 0 评论 -
【33】面试题40:数组中只出现一次的数字
【1】题目题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是 O(n),空间复杂度是O(1)。【2】思路//异或运算 相同为1 不同为0//当异或的两个元素为1或者0的时候,结果为0或者1,int a = 1 ^ 1;//a=0//当异或的两个元素大于1时,结果为两个元素相加,int a = 1 ^ 2;//a=3这两个题目都在强调一个(或两个)数字只出现一次,其他的出现两次。这有什么意义呢?我们想到异或运算的一个性质:任何原创 2021-04-09 10:49:15 · 88 阅读 · 0 评论 -
【32】面试题39:二叉树的深度
【1】题目题目一:输入一棵二叉树的根结点,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。【2】思路如果一棵树只有一个结点,它的深度为1。如果根结点只有左子树而没有右子树,那么树的深度应该是其左子树的深度加1;同样如果根结点只有右子树而没有左子树,那么树的深度应该是其右子树的深度加1。如果既有右子树又有左子树,那该树的深度就是其左、右子树深度的较大值再加1。比如在图6.1的二叉树中,根结点为1的树有左右两个子树,其左右子树的根结点分别为原创 2021-04-09 10:46:38 · 210 阅读 · 0 评论 -
【31】 面试题38:数字在排序数组中出现的次数
【1】题目题目:统计一个数字在排序数组中出现的次数。例如输入排序数组{1,2, 3,3,3,3,4,5}和数字3,由于3在这个数组中出现了4次,因此输出4。【2】思路我们先分析如何用二分查找算法在数组中找到第一个k。二分查找算法总是先拿数组中间的数字和k作比较。如果中间的数字比k大,那么k只有可能出现在数组的前半段,下一轮我们只在数组的前半段查找就可以了。如果中间的数字比k 小,那么k 只有可能出现在数组的后半段,下一轮我们只在数组的后半段查找就可以了。如果中间的数字和 k 相等呢?我们先判断这原创 2021-04-08 16:44:16 · 125 阅读 · 0 评论 -
【30】面试题37:两个链表的第一个公共结点
【1】题目题目:输入两个链表,找出它们的第一个公共结点。链表结点定义如下:【2】思路(1)经过分析我们发现,如果两个链表有公共结点,那么公共结点出现在两个链表的尾部。如果我们从两个链表的尾部开始往前比较,最后一个相同的结点就是我们要找的结点。可问题是在单向链表中,我们只能从头结点开始按顺序遍历,最后才能到达尾结点。最后到达的尾结点却要最先被比较,这听起来是不是像“后进先出”?于是我们就能想到用栈的特点来解决这个问题:分别把两个链表的结点放入两个栈里,这样两个链表的尾结点就位于两个栈的栈顶,接原创 2021-04-08 11:20:50 · 218 阅读 · 0 评论 -
【29】面试题36:数组中的逆序对
【1】题目题目:在字符串中找出第一个只出现一次的字符。如输入"abaccdeff",则输出'b'。【2】思路第一次扫描时,在哈希表中更新一个字符出现的次数的时间是O(1)。如果字符串长度为n,那么第一次扫描的时间复杂度是O(n)。第二次扫描时,同样O(1)能读出一个字符出现的次数,所以时间复杂度仍然是O(n)。这样算起来,总的时间复杂度是O(n)。同时,我们需要一个包含256个字符的辅助数组,它的大小是1K。由于这个数组的大小是个常数,因此可以认为这种算法的空间复杂度是O(1)。【3】代码原创 2021-04-07 15:15:30 · 165 阅读 · 0 评论 -
【28】面试题34:丑数
【1】题目题目:我们把只包含因子2、3和5的数称作丑数(UglyNumber)。求按从小到大的顺序的第1500个丑数。例如6、8都是丑数,但14不是,因为它包含因子7。习惯上我们把1当做第一个丑数。【2】思路(1)所谓一个数m是另一个数n的因子,是指n能被m整除,也就是n% m== 0。根据丑数的定义,丑数只能被2、3和5整除。也就是说如果一个数能被2整除,我们把它连续除以2;如果能被3整除,就连续除以3;如果能被5整除,就除以连续5。如果最后我们得到的是1,那么这个数就是丑数,否则不是。(原创 2021-04-07 11:52:05 · 213 阅读 · 0 评论 -
【27】面试题33:把数组排成最小的数
【1】题目题目:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3, 32, 321},则打印出这3个数字能排成的最小数字321323。【2】思路(1)这个题目最直接的做法应该是先求出这个数组中所有数字的全排列,然后把每个排列拼起来,最后求出拼起来的数字的最大值。求数组的排列和面试题 28“字符串的排列”非常类似,这里不再详细介绍。根据排列组合的知识,n个数字总共有n!个排列。(2)根据题目的要求,两个数字 m 和 n 能拼接成数字原创 2021-04-07 11:02:39 · 104 阅读 · 0 评论 -
【26】面试题32:从1到n整数中1出现的次数
【1】题目题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。例如输入12,从1到12这些整数中包含1 的数字有1,10,11和12,1一共出现了5次【2】思路如果希望不用计算每个数字的1 的个数,那就只能去寻找1 在数字中出现的规律了。为了找到规律,我们不妨用一个稍微大一点的数字比如21345作为例子来分析。我们把从1到21345的所有数字分为两段,一段是从1到1345,另一段是从1346到21345。我们先看从1346到21345中1出现的次数。1的出现分为两种情况。首先分原创 2021-04-06 21:26:07 · 181 阅读 · 0 评论 -
【25】面试题31:连续子数组的最大和
【1】题目题目:输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。【2】思路【3】代码// Test30.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//#include "pch.h"#include <iostream>#include<vector>using namespace std;//连续和最大的数组 //数组规律解原创 2021-04-05 15:46:35 · 114 阅读 · 0 评论 -
【24】面试题30:最小的k个数
【1】题目题目:输入n个整数,找出其中最小的k个数。例如输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。【2】思路我们可以先创建一个大小为k 的数据容器来存储最小的k 个数字,接下来我们每次从输入的 n 个整数中读入一个数。如果容器中已有的数字少于k 个,则直接把这次读入的整数放入容器之中;如果容器中已有k 个数字了,也就是容器已满,此时我们不能再插入新的数字而只能替换已有的数字。找出这已有的 k 个数中的最大值,然后拿这次待插入的整数和最大值进行比较。如果待插入原创 2021-04-05 14:55:58 · 111 阅读 · 0 评论 -
【23】面试题29:数组中出现次数超过一半的数字
【1】题目题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。【2】思路数组中有一个数字出现的次数超过数组长度的一半,也就是说它出现的次数比其他所有数字出现次数的和还要多。因此我们可以考虑在遍历数组的时候保存两个值:一个是数组中的一个数字,一个是次数。当我们遍历到下一个数字的时候,如果下一个数字和我们之前保存的数字相同,则次数加1;如果下一个数字和我们之原创 2021-04-05 11:58:47 · 154 阅读 · 0 评论 -
【22】面试题28:字符串的排列
【1】题目题目:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。【2】思路【3】代码#pragma once#ifndef CHANGECHAR_H#define CHANGECHAR_Hclass ChangeChar{ public: ChangeChar(); ~ChangeChar(); //两个函数函数名相同,形参不同,相当于多态原创 2021-04-05 10:53:41 · 81 阅读 · 0 评论 -
【21】面试题27:二叉搜索树与双向链表
【1】题目题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。比如输入图4.12中左边的二叉搜索树,则输出转换之后的排序双向链表。【2】思路注:根结点、左子树和右子树。在把左、右子树都转换成排序的双向链表之后再和根结点链接起来,整棵二叉搜索树也就转换成了排序的双向链表。按照中序遍历的顺序,当我们遍历转换到根结点(值为10的结点)时,它的左子树已经转换成一个排序的链表了,并且处在链表中的最后一个结点是当前值最大的结点。我们原创 2021-04-04 22:32:13 · 106 阅读 · 0 评论 -
【20】面试题26:复杂链表的复制
【1】题目题目:请实现函数ComplexListNode*Clone(ComplexListNode*pHead),复制一个复杂链表。在复杂链表中,每个结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling 指向链表中的任意结点或者NULL。结点的C++定义如下:【2】思路(1)原始链表(2)复制原始链表的节点(3)复制原始链表的随机指针(4)拆分原始链表【3】代码#pragma once#ifndef COMPLEXLISTC原创 2021-04-04 21:39:20 · 131 阅读 · 0 评论 -
【19】面试题24二叉搜索树的后序遍历序列和25二叉树路径为定值
24 二叉搜索树的后序遍历序列【1】题目题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。【2】思路(1)后序遍历最后的一个节点为根节点;(2)小于最后的一个节点的为左子树,大于最后一个节点为右子树;(3)判断左子树和右子树是否为二叉搜索树(4)二者都为二叉搜索树则结果为后序遍历的结果,反之不是面试题25:二叉树中和为某一值的路径【1】题目题目:输入一棵.原创 2021-04-03 15:30:51 · 82 阅读 · 0 评论 -
【18】面试题23:分层打印二叉树
【1】题目题目:从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印。例如输入图4.5中的二叉树,则依次打印出8、6、10、5、7、9、11【2】思路【3】代码#pragma once#ifndef PRINTBINARY_H#define PRINTBINARY_Hstruct BinaryNode{ int value; BinaryNode* leftptr; BinaryNode* rightptr;};class Prin原创 2021-04-02 19:23:20 · 144 阅读 · 0 评论 -
【17】面试题22:栈的压入、弹出序列
【1】题目题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1、2、3、4、5 是某栈的压栈序列,序列4、5、3、2、1 是该压栈序列对应的一个弹出序列,但 4、3、5、1、2 就不可能是该压栈序列的弹出序列。【2】思路如果下一个弹出的数字刚好是栈顶数字,那么直接弹出。如果下一个弹出的数字不在栈顶,我们把压栈序列中还没有入栈的数字压入辅助栈,直到把下一个需要弹出的数字压入栈顶为止。如果所有的数字都压入栈了仍然没有找原创 2021-03-29 20:00:00 · 182 阅读 · 0 评论 -
【16】包含min函数的栈
【1】题目【2】思路建立辅助栈【3】代码#pragma once#ifndef MINELEMENT_H#define MINELEMENT_H#include<stack>#include<vector>#include <assert.h>#include<iostream>using namespace std;//定义类模板template<typename T>class MinEl.原创 2021-03-25 11:04:36 · 92 阅读 · 0 评论 -
【15】面试题20:顺时针打印矩阵
【1】题目【2】思路【3】代码#pragma once#ifndef PRINT_MATRIX#define PRINT_MATRIX#include<vector>using namespace std;class PrintMatrix{ public: PrintMatrix(); ~PrintMatrix(); void ShowMatrix(vector<vector<int>> array, int row原创 2021-03-23 15:24:17 · 112 阅读 · 0 评论 -
【14】剑指offer-面试题17(合并链表)
【1】题目题目:输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。【2】思路递归思想双链表【3】代码//合并链表ListNode * Merge(ListNode * pHeadA, ListNode * pHeadB){ ListNode * ptrA, *ptrB, * mHead; if (pHeadA==NULL) { return pHeadB; } else if (pHeadB == NULL) { return p原创 2021-02-24 16:08:59 · 90 阅读 · 0 评论 -
【13】剑指offer-面试题16(翻转链表)
【1】题目题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点【2】思路双指针,递归【3】代码struct ListNode{ int m_nValue; ListNode * m_pNext;};ListNode * ReversedList(ListNode * pHead){ ListNode* cur = NULL, *pre = pHead; while (pre != NULL) { ListNode* t = pre-原创 2021-02-23 16:00:37 · 110 阅读 · 0 评论 -
【12】剑指offer-面试题15(链表中倒数第k个结点)
【1】题目题目:输入一个链表,输出该链表中倒数第 k 个结点。为了符合大多数人的习惯,本题从1 开始计数,即链表的尾结点是倒数第1 个结点。例如一个链表有6个结点,从头结点开始它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个结点是值为4的结点。【2】思路【3】代码test15.h#pragma oncestruct ListNode{ int m_nValue; ListNode * m_pNext;};void creat(ListNode *原创 2021-02-22 17:26:09 · 156 阅读 · 0 评论 -
【11】剑指offer-面试题14(调整数组顺序使奇数位于偶数前面)
【1】题目【2】思路设置两个指针,一个向后遍历负责奇数,一个向前遍历负责偶数。创建一个bool函数负责判断转换条件。【3】代码// test40.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//#include <iostream>#include <stdio.h>#include<time.h>#include<cstring>using namespace std;//调整数原创 2020-08-20 11:44:05 · 113 阅读 · 0 评论 -
【10】剑指offer-面试题13(O(1)时间删除节点)
【1】题目【2】思路删除的链表节点有四种情况:(1)空链表,返回无;(2)一个节点,头尾一样,删除节点,头尾清零;(3)尾部节点,需要遍历链表,找到前一个节点,然后删除后一个节点。(4)中间任意位置节点,找到待删除节点的下一个节点,用下一个节点覆盖当前节点,然后删除后一个节点即可。【3】代码#include <stdio.h>#include <iostream>#include<vector>#include<time.原创 2020-08-19 17:12:46 · 111 阅读 · 0 评论 -
【9】剑指offer-面试题12(打印1到n的最大n位数)
【1】题目【2】思路(1)一般解法(2)正确解法【3】代码#include <stdio.h>#include <iostream>#include<vector>#include<time.h>#include<cstring>using namespace std;bool Increment(char *number){ bool isOverflow = false; int nTak原创 2020-08-18 17:13:16 · 107 阅读 · 0 评论 -
【8】剑指offer-大数运算
【1】题目10000的阶乘怎么算?答:“10000”这个数字太大了,无论用什么数据类型保存结果都会溢出。现在使用数组来模拟数字,这样无论结果数字有多大,只要数组的长度够长就能表示出来,用这个办法可以进行大数据的运算。【2】思路用大数运算方法,数组存放。【3】代码#include <stdio.h>#include <iostream>#include<vector>#include<time.h>using namespa原创 2020-08-18 10:57:46 · 222 阅读 · 0 评论 -
【7】剑指offer-面试题11(指数运算)
【1】题目【2】思路(1)底数有四种情况:小于0,等于0,大于0小于1,大于1(2)同样指数也存在四种情况:小于0,等于0,大于0小于1,大于1(但是int不考虑0到1范围的数)(3)因此有四种情况:分别为底数为0,指数小于1,指数为0,指数大于1注意 高精度的数判断是否相等,不能直接用==号,因为尾部精度不同,需要将两个数相减如果差值保存在一定区域,则可以认为相等。【3】代码#include <iostream>#include<vector>..原创 2020-08-17 17:31:35 · 268 阅读 · 0 评论 -
【6】剑指offer-面试题9(递归---斐波拉契数列)
【1】题目【2】思路(1)直接调用递归,输入的数过大后会产生指数级的时间消耗;(2)累加计算,时间消耗少。【3】代码#include <iostream>#include<vector>#include<time.h>using namespace std;//原始的斐波拉契递归方法,重复计算,指数级算法long long Fibonacci1(int n) { int result[2] = { 0,1 }; if (n&原创 2020-08-17 14:43:10 · 189 阅读 · 0 评论 -
【5】剑指offer-面试题8(旋转数组的最小数字)
【1】题目【2】思路(1)34512没有重复的类型的,二分查找法。(2)110111,01重复类型的,顺序查找。【3】代码// Test3.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//#include <iostream>#include<vector>using namespace std;//顺序查找int select(vector<int> number){ if (number原创 2020-08-17 13:56:49 · 101 阅读 · 0 评论 -
【4】剑指offer-面试题7(两个栈实现队列)
【1】题目【2】思路先进入stack1,然后在出栈放入stack2;【3】源码#include <iostream>#include<fstream>#include<stack>#include <stdio.h>#include <stdlib.h>using namespace std;//两个栈实现队列template<class T> class CQueue{public:原创 2020-08-15 17:36:26 · 102 阅读 · 0 评论 -
【3】剑指offer-面试题5(反序打印链表)
【1】题目【2】思路递归实现【3】源码#include <iostream>#include<fstream>#include<vector>#include <stdio.h>#include <stdlib.h>#define OK 0#define ERROR -1#define MALLOC_ERROR -2 using namespace std;//注意原创 2020-08-15 11:38:45 · 107 阅读 · 0 评论 -
【2】剑指offer-面试题4(替换空格)
【1】题目【2】思路【3】源代码#include <iostream>#include<fstream>#include<vector>using namespace std;//用%20代替原有的空格void ReplaceBlank(char str[]) { //字符串若为空则直接退出 int len=strlen(str); if (len == 0) { return; } //求取字符串的长度和空格的个数原创 2020-08-14 19:23:52 · 100 阅读 · 0 评论 -
【1】剑指officer-面试题3(二维数字数字查找)
// test2.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//#include <iostream>#include<fstream>#include<vector>using namespace std;//寻找二维数组中的一个元素bool selectnum(vector<vector<int>> matrix, int num){ bool flag = false; if ...原创 2020-08-14 14:45:45 · 101 阅读 · 0 评论