剑指Offer系列
主要以剑指Offer 面试题展开讲解
林夕07
从事Windows桌面开发,GIS平台的二次开发,地图服务、仿真等等。日常分享一些使用技巧。曾获得新星计划第三季人工智能赛道TOP5;阿里云专家博主
展开
-
剑指Offer - 面试题7:重构二叉树 (力扣 - 105、从前序与中序遍历序列构造二叉树)
题目输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如:输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树如下图。返回该二叉树的头节点。 3 / \ 9 20 / \ 15 7二叉树定义如下:struct BinaryTreeNode{ int m_nValue; BinaryTreeNode* m_pLeft; BinaryT原创 2021-05-11 12:14:10 · 338 阅读 · 0 评论 -
力扣 - 102、二叉树的层序遍历(剑指Offer - 面试题32:从上到下打印二叉树)
题目给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。(有改动)示例:二叉树:[3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7输出层序遍历的结果3 9 20 15 7分析迭代法用一个队列来存储当前层数的节点地址,每次从队列头部取出一个节点,然后判断是否为NULL,若不为空则输出当前节点,并把左右子节点存入队列尾部。直到队列中没有元素为止。因为这里拿c语言实现,所以用数组原创 2021-05-07 22:52:21 · 223 阅读 · 0 评论 -
剑指Offer - 面试题47:礼物的最大价值
题目在一个m*n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向左向下移动一格,直到到达棋盘的右下角。给定一个棋盘及其上面的礼物,请计算你最多能拿到多少价值的礼物?例如,在下面的棋盘中,如果沿着带下画线的数字的路线(1、12、5、7、7、16、5)。那么我们能拿到最大价值为53的礼物。分析动态规划我们创建一个等同棋盘的二维数组,每个位置用记录前一步到这一步的能拿到的最多价值。如下图,每一步都是拿到的最多价值。空间复杂度为O(n原创 2021-06-04 23:42:29 · 247 阅读 · 0 评论 -
剑指Offer - 面试题40:最小的k个数
题目输入n个整数,找出其中最小的k个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。分析排序法我们可以将这个整数数组先排序在取出前k个值就完成了题目要求。若题目要求不能修改原数组,这个时候我们还需要自己创建一个数组。这里只实现不能修改原数组的解法,排序函数用的是C库函数C++#include <iostream>#include <cstdlib>using namespace std;int compar_int(con原创 2021-06-03 12:32:51 · 185 阅读 · 2 评论 -
剑指Offer - 面试题16:数值的整数次方
题目实现函数double Power(double base, int exponet),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。分析暴力法exponet次方,循环exponet次就可以了。时间复杂度为O(n),O(1);C#include<stdio.h>#include<stdlib.h>//暴力法double Power(double base, int exponent){ int i = 0; double sum原创 2021-04-28 19:53:53 · 147 阅读 · 0 评论 -
剑指Offer - 面试题24:反转链表
题目定义一个函数,输入一个链表的头就额点,反转该链表并疏忽从反转后链表的头节点。链表节点定义如下:typedef int TElemType;//链表节点值的数据类型struct ListNode{ TElemType Data; ListNode* Next;};分析反转链表需要用到三个指针。later指针和node指针用于转方向,front指针用于记录下一个节点位置。反转核心四步如下图C++#include <iostream>using name原创 2021-05-18 18:30:19 · 190 阅读 · 1 评论 -
剑指Offer - 面试题64:求1+2+...+n
题目求1+2+…n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)分析递归法当我们第一眼看见题,循环、递归、还有公式法等。但是当我们看完要求后,发现我们想的各种解法都包含了条件中禁止的要求。循环必须要for、while、do while,所以pass掉。公式法必须要乘除法,也pass掉。那么我们只能从递归下手了。我们先写一个不受限制的递归求累加int sumNums(int n){ if (n <= 0)原创 2021-05-20 14:25:38 · 320 阅读 · 2 评论 -
剑指Offer - 面试题25:合并俩个排序的链表
题目输入俩个递增排序的链表,合并这俩个链表并使新链表中的节点仍然是递增序列。例如下图链表1和链表2,合并后的升序链表为链表3,链表节点定义如下:typedef int TElemType;//链表节点值的数据类型struct ListNode{ TElemType m_nValue; ListNode* m_pNext;};分析我们可以构造出来一个链表。表头不存储数据,定义俩指针p1和p2分别指向链表1和链表2表头。再创建一个记录新的链表尾部的指针previously。然原创 2021-05-19 14:47:50 · 285 阅读 · 0 评论 -
剑指Offer - 面试题27:二叉树的镜像
题目请完成一个函数,输入一棵二叉树,该函数输出它的镜像。二叉树节点的定义如下:typedef int TElemType; /* 树结点的数据类型,目前暂定为整型 */struct BianryTreeNode{ TElemType m_nValue; BianryTreeNode* m_pLeft, * m_pRight;//左右孩子节点};分析先画出一对二叉树,并写出三序列遍历结果,一会用于判断新的二叉树是否为原二叉树的镜像。观察下图,发现就是左右对调,本质就是依次交换该节点的左原创 2021-05-19 17:50:52 · 146 阅读 · 0 评论 -
剑指Offer - 面试题5:替换空格
题目请实现一个函数,把字符串 s 中的每个空格替换成"%20"。示例 1:输入:s = “We are happy.”输出:“We%20are%20happy.”限制:0 <= s 的长度 <= 10000分析本题唯一难点就是如何将一个字符替换为三个,这样就会加长字符串。暴力解法直接双层循环,时间复杂度O(n^2) 空间复杂度为O(1)C#include<stdio.h>#include<string.h>void ReplaceBlank(原创 2021-04-12 23:45:40 · 151 阅读 · 0 评论 -
剑指Offer - 面试题6:从尾到头打印链表
题目输入一个链表的头节点,从尾到头反过来打印出来每个节点的值。链表节点定义如下:struct ListNode{ int m_nKey; struct ListNode* m_pNext;};思路栈方法从尾到头完全符合栈的特性,我们直接拿栈来存储就可以顺利输出。(c语言需要自己构造栈,这块用数组代替。这里就只构造一个链表)C#include<stdio.h>#include<stdlib.h>#include<time.h>struct L原创 2021-04-20 19:11:10 · 177 阅读 · 0 评论 -
剑指Offer - 面试题15:二进制中1的个数
题目请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如,把9表示成二进制是1001,有俩位是1.因此,如果输入9,则函数输出2。类似题目在leetcoed上191. 位1的个数也有。分析求余法我们让num每次%2求余,得到是1就让count++;然后让num/2。直到num为0为止。C#include<stdio.h>int NumberOf(int n){ int count = 0; while (n > 0) { if (n % 2 ==原创 2021-04-26 15:44:53 · 211 阅读 · 0 评论 -
剑指Offer - 面试题14:剪绳子
题目给你一根长度为n的绳子,请把绳子剪成m段(m,n都是整数,n>1并且m>1),每段绳子的长度j记为k[0],k[1],…k[m]。请问k[0]k[1]…*k[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。分析动态规划长度n的绳子,我们剪第一刀的时候有(n-1)种方法。分别为:1,2,3,…,n-1。这是一个自顶向下的递归,在之前剑指Offer - 面试题10:斐波那契数列中讲过从上往下,复杂度是以n的指数增长原创 2021-04-25 17:51:26 · 490 阅读 · 0 评论 -
剑指Offer - 面试题30:包含min函数的栈
题目实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作。本题在《程序员代码面试指南-左程云》 第一章 栈和队列 中也有要求pop、push、getMin操作的时间复杂度都是O(1)设计的栈类型可以使用线程的栈结构分析双栈法我们可以用一个stackmin(辅助站)栈用来存储每次出栈stackdata(数据栈)或者入栈之后栈中的最小值。入栈。将数据与stackmin的栈顶元素对比,若发现,新来的值小于等于栈顶值,就将该数据也放在stackmin中。否则不添加。原创 2021-05-08 23:34:36 · 223 阅读 · 0 评论 -
剑指Offer - 面试题21:调整数组顺序使奇数位于偶数前面
题目输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。分析暴力法最简单能想到的就是从前到后依次遍历若发现是偶数,先保存当前元素,将后面全部往前移动,然后把保存的元素给到最后那个位置。时间复杂度为O(n2),空间复杂度为O(1);C#include<stdio.h>#include<assert.h>//暴力法void ReordeOddEven(int* pData, unsigned int l原创 2021-05-07 14:53:52 · 134 阅读 · 0 评论 -
剑指Offer - 面试题13:机器人的运动范围
题目地上有一个m行n列的方格。一个机器人从坐标(0,0)的格子开始移动,它每次可以向左、右、上、下移动一格,但不能进入行坐标与列坐标的位数之和大于k的格子。例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+18.但是不能进入方格(35,38),因为3+5+3+8=19。请问机器人能够达到多少个格子分析dfs + 回溯我们可以设置一个二维数组用来区别该位置是否计算过。初始化成0,如果计算过就设置为-1。然后从(0,0)开始,如果(0,0)都不符合那就所有位置都不符合了。然后与依次向原创 2021-04-24 16:31:08 · 151 阅读 · 0 评论 -
剑指Offer - 面试题11:旋转数组的最小数字
题目把一个数组最开始的若干个元素搬到数组末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素,例如,数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。分析暴力法我们不考虑任何特点,直接一次循环求解。C#include<stdio.h>#include<stdlib.h>int Min(int* n, int length){ int min = INT_MAX; int i = 0; for (原创 2021-04-22 12:34:36 · 132 阅读 · 0 评论 -
剑指Offer - 面试题49:丑数
题目我们把只包含因子2、3、5的数称为丑数(Ugly Number)。求按照从小到大的顺序的第1500个丑数。例如,6、8都是丑数,但14不是,因为它包含因子7.习惯上我们把1当作第一个丑数。分析暴力法从1开始每个数字都判断,若是丑数,计数器就+1。前20个丑数为:1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 25, 27, 30, 32, 36。C++#include <iostream>using namespace原创 2021-05-19 21:55:54 · 671 阅读 · 0 评论 -
剑指Offer - 面试题23:链表中环的入口节点
题目如果一个链表中包含环,如何找出环的入口节点?例如,在下图中的链表中,环的入口节点是节点3。分析将这个问题解剖开。分为俩步判断是否有环有环再找入口节点第一个问题:我们用快慢指针来判断,只要相遇就有环,快指针走到头就是没有环。第二个问题:与剑指Offer - 面试题22:链表中倒数第K个节点第二种方法思想相似,可以先去看看这个题。我们先定义链表头到入口距离m,环的长度为n。那么可以先让快指针从头开始走环的长度n,那么快指针走到环的入口还需要走m长度。刚好此时慢指针也一起走,走到入口处相遇原创 2021-05-18 17:37:29 · 181 阅读 · 0 评论 -
剑指Offer - 面试题22:链表中倒数第K个节点
题目输入一个链表,输出该链表中倒数第K个节点。为了和服大多数人习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如,一个链表有6个节点,从头节点开始,它们的值依次是1、2、3、4、5、6.这个链表的倒数第3个节点是值为4的节点。链表节点定义如下:分析二次遍历我们很容易就想到,可以先遍历一次得出链表的长度,然后再从头开始向后移动len-k个节点。C++#include <iostream>using namespace std; /*以下为链表的实现*/typedef原创 2021-05-18 17:01:19 · 204 阅读 · 6 评论 -
剑指Offer - 面试题12:矩阵中的路径
题目请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵总向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。如,在下面的3*4的矩阵中包含一条字符串“bfce”的路径(路径中的字母用下画线标出)。但矩阵中不包括字符串“avfv”的路径,因为字符串的第一个字符占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。分析dfs + 回溯法双层循环遍历先找第一个符合的元素,然后再分别向上原创 2021-04-22 19:24:34 · 271 阅读 · 0 评论 -
剑指Offer - 面试题8:二叉树的下一个节点
题目给定一颗二叉树和其中的一个节点,如何找出中序便利序列的下一个节点?树中的节点除了有俩个分别指向左、右子节点的指针,还有一个指向父节点的指针。结构如下typedef int TElemType; /* 树结点的数据类型,目前暂定为整型 */struct BinaryTreeNode{ TElemType m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight; BinaryTreeNode* m_pParent;};原创 2021-05-18 13:21:50 · 186 阅读 · 2 评论 -
剑指Offer - 面试题1:赋值运算符函数
题目如下为类型CMyString的声明,请为该类型添加赋值运算符函数。class CMyString{public: CMyString(char* pData = nullptr); CMyString(const CMyString& str); ~CMyString(void);private: char* m_pData;};分析该代码并不难,但是有几个值得注意的点。1、返回值声明为当前类型的引用,且返回自身的引用(*this)。目的是为了可以连续赋值.如:C原创 2021-04-18 20:53:55 · 181 阅读 · 0 评论 -
剑指Offer - 面试题17:打印从1到最大的n位数
题目输入数字n,按顺序打印从1到最大的n位十进制数。比如输入3,则打印出1、2、3一直到最大的3位数999。分析暴力法打印的最小值为1,打印的最大值=10n-1。我们可以一次循环遍历,从i开始遍历到10n-1; 时间复杂度O(n),空间复杂度O(1)。C#include<stdio.h>void PrintToMaxOfNDigits(int n)//打印函数{ int max = 10 * n - 1; int i = 0; for(i = 0; i < max原创 2021-04-29 13:53:20 · 189 阅读 · 0 评论 -
剑指Offer - 面试题18-1:删除链表的节点
题目在O(1)时间内删除链表节点。给定单项链表的头节点和一个节点指针,定义一个函数在O(1)时间内删除该节点。链表节点与函数的定义如下:typedef struct ListNode { int m_nValue; struct ListNode* m_pNext;}ListNode;void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted);分析线性查找要删除的位置有三种情况1、最后节点要删除,直接删除然后前一个结原创 2021-04-29 14:57:05 · 254 阅读 · 0 评论 -
剑指Offer - 面试题9:用俩个栈实现队列
题目用俩个栈实现一个队列。队列的声明如下,请实现它的俩个函数appendTail和deleteHead,分别完成在队列尾部插入节点和在队列头部删除节点的功能。template <typename T> class CQueue{public: CQueue(void); ~CQueue(void); void appendTail(const T& node); T deleteHead();private: stack<T> stack1; sta原创 2021-05-07 21:38:08 · 160 阅读 · 0 评论 -
剑指Offer - 面试题10:斐波那契数列
题目一 求斐波那契数列的第n项写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项。斐波那契数列的定义如下:分析递归法给出的公式用递归是最简单的,但是也是效率很低的。C#include<stdio.h>long long Fibonacci(int n){ if (n <= 0) { return 0; } if (n == 1) { return 1; } return Fibonacci(n - 1) + Fibonacci(原创 2021-04-21 21:41:56 · 248 阅读 · 0 评论 -
剑指Offer - 面试题3:数组中重复的数字
题目在一个长度为n的数组里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次,请找出数组中任意一个重复的数字。例如:如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3。分析暴力法先排序再查找重复,时间复杂度O(nlg(n)),空间复杂度为O(1)。#include<stdio.h>#include<stdlib.h>int compar_int(const void* p原创 2021-04-18 22:58:38 · 127 阅读 · 0 评论 -
剑指Offer - 面试题28:对称的二叉树
题目请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。例如,在下图中,只有第一颗二叉树是对称的。而另外俩颗不是。分析对称遍历对称的二叉树本质就是左右节点相同就好,所以我们可以用俩种对称的遍历方法将指向节点的指针存入容器中(如果放的是节点值的话,就如上图第三个二叉树,会造成混乱),然后一一对比,若有不同时就表示不是对称二叉树。选取:根左右 和 根右左 做对比C++#include <iostream>#include <vecto原创 2021-05-20 13:25:12 · 188 阅读 · 1 评论