剑指offer
Yfan133
luka,up up!
展开
-
【剑指38】字符的排列
文章目录方法一:dfs + 剪枝:时间O(n!n!n!),空间O(n)方法一:dfs + 剪枝:时间O(n!n!n!),空间O(n)解题思路:对字符串进行全排列,将每次不同排列的结构插入数组中通过dfs + 循环遍历数组,并交换元素位置,实现全排列全排列过程中可能出现数组中多个元素重复占用同一位置,造成结果重复因此采用一个固定大小的数组,每排一次位置让元素对应下标++class Solution {public: vector<string> ans; vec原创 2021-03-11 15:47:23 · 48 阅读 · 0 评论 -
【剑指37】序列化二叉树
文章目录方法一:dfs:时间O(n),空间O(n)方法一:dfs:时间O(n),空间O(n)题解:序列化:规定序列化的格式:一个数据之后跟上逗号,如果空树则用 # 代替占位先序遍历二叉树,如果是空树则插入 #,如果不空则将数据转换成string类型并插入,最后添加逗号反序列化根据序列化的格式进行反序列化,如果当前字符是# 则赋空如果不是# ,则动态创建节点时间:O(n) 遍历二叉树的所有节点,遍历 string 的所有元素都是O(n)空间:O(n) 最坏情况二叉树是单支树原创 2021-03-11 15:18:03 · 48 阅读 · 0 评论 -
【剑指36】二叉搜索树与双向链表
文章目录方法一:中序遍历:时间 O(n),空间 O(n)方法一:中序遍历:时间 O(n),空间 O(n)解题思路:二叉搜索树的中序遍历是一个递增的序列因此遍历二叉树,回溯前需要记录前驱节点在左树回溯之后将前驱节点和当前节点进行链接题解记录一个头结点 head 和前驱节点 prev,对二叉树进行中序遍历左树回溯的时候进行判断,若head为空说明到达了值最小的头结点,让 head = prev = root若 head 不空,则将 root 的左树指向 prev ,prev的右树指向 r原创 2021-03-11 14:40:50 · 48 阅读 · 0 评论 -
【剑指35】复杂链表的复制
文章目录方法一:先链接再分离,时间O(n),空间O(n)方法一:先链接再分离,时间O(n),空间O(n)题解:复制每个节点,并将之链接到原链表中调整 random 节点指向,random的下一个节点(random不空)分离链表/*// Definition for a Node.class Node {public: int val; Node* next; Node* random; Node(int _val) { val原创 2021-03-10 15:24:10 · 49 阅读 · 0 评论 -
【剑指33】二叉搜索树的后序遍历
文章目录方法一:递归分治:时间O(n2n^2n2)、空间O(n)方法二:单调栈:时间 O(n),空间O(n)方法一:递归分治:时间O(n2n^2n2)、空间O(n)解题思路:利用后序遍历的特点:左树 | 右树 | 根结点,检查每个根的左右子树是否满足二叉搜索树特性若当前根结点满足搜索树特性,则继续在该节点的左右子树中检查题解:递归分治法:定义一个根结点,遍历数组,直到节点值比根结点大。记录当前的位置pos,继续向后遍历,后序节点应该满足都大于根结点。分治:检查pos位置两边的树,也就是原创 2021-03-10 15:20:25 · 44 阅读 · 0 评论 -
【剑指33】二叉搜索树的后序遍历序列
方法一:分治思想:时间 O(n2n^2n2),空间 O(n)题解:利用后序遍历的规则:左树 | 右树 | 根节点,将后序遍历序列分成一个个子树检查每一颗子树是否满足二叉搜索树的特性:左树都比根节点小如果都满足则说明数组正确缺点:每次遍历数组都只能检测一个根节点,因此检查所有根节点需要O(n2n^2n2)的时间时间:遍历一次数组只能减少一个节点,而每次遍历都需要O(n)时间空间:当二叉树退化成单只树则需要O(n)的空间class Solution {public: bool ve原创 2021-03-01 15:40:18 · 92 阅读 · 0 评论 -
【剑指32】从上到下打印二叉树 I、II、III
文章目录方法一:借助队列层序遍历:时间O(n),空间O(n)方法一:借助队列层序遍历:时间O(n),空间O(n)时间:遍历二叉树需要O(n)的时间空间:当为平衡二叉树时,最多有 (n+1)/2 个节点,也就是O(n)的空间复杂度题解:队列初始化插入根节点出队,把当前节点的值插入数组,如果节点左树不空则入队,右树不空则入队/** * Definition for a binary tree node. * struct TreeNode { * int val; *原创 2021-02-20 15:04:19 · 66 阅读 · 0 评论 -
【剑指31】栈的压入、弹出序列
文章目录方法一:模拟栈的插入删除:时间O(n),空间O(n)方法一:模拟栈的插入删除:时间O(n),空间O(n)题解:给出一个压栈和出栈序列,则这组序列入栈和出栈顺序可以唯一确定借助一个栈结构模拟栈的压入和弹出操作入栈:直接插入压栈序列的元素,每插入一个元素之后都要检测出栈:插入一个元素之后检测,栈内元件是否和出栈元素响应位置的元素相同,如果相同则出栈最后检测栈是否为空,则可以判断出栈顺序是否正确class Solution {public: bool validateSta原创 2021-02-20 14:49:35 · 79 阅读 · 0 评论 -
【剑指30】包含min函数的栈
文章目录方法一:双栈模拟最小栈:时间O(1),空间O(n)方法一:双栈模拟最小栈:时间O(1),空间O(n)题解:要保证push(),pop(),min()等函数的时间复杂度都是O(1),因此我们管理一个最小栈,专门用来存放当前栈中最小的值push():push栈直接插入,min栈:判断栈顶元素和插入元素的大小,如果插入元素较小或者相等则插入pop():push栈直接删除,min栈:判断栈顶元素是否和push栈删除的元素相同,相同则删除class MinStack { privat原创 2021-02-19 16:57:17 · 62 阅读 · 0 评论 -
【剑指29】顺时针打印矩阵
文章目录方法一:模拟路径:时间O(nm),空间O(1)方法一:模拟路径:时间O(nm),空间O(1)题解:模拟矩阵的遍历方法,按层划分,一层一层的打印,直到打印完最内层的元素从左到右遍历上侧元素,依次为(top, left) 到 (top, right)从上到下遍历右侧元素,依次为(top + 1, right) 到 (bottom, right)如果 left <right && top < bottom 说明可以向左遍历,依次为(bottom, right -原创 2021-02-19 16:44:02 · 54 阅读 · 0 评论 -
【剑指25】合并两个排序的链表
文章目录方法一:重新拼接两个链表:时间O(mn),空间O(1)方法二:递归(不创建头结点):时间O(mn),空间O(m) m>n方法一:重新拼接两个链表:时间O(mn),空间O(1)题解:建立头结点将两个链表按大小顺序拼接到头结点之后循环结束,将剩下的一节拼接到后面/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * Lis原创 2021-02-18 19:46:02 · 42 阅读 · 0 评论 -
【剑指28】对称二叉树
文章目录方法一:左右子树是否对称,时间O(n),空间O(n)方法一:左右子树是否对称,时间O(n),空间O(n)题解:对于两个对称的节点有node1->val == node2->val,两节点值相同node1->left->val == node1->right->val,node1的左树和node2的右树相同node1->right->val == node2->left->val,node1的右树和node2的左树相同/**原创 2021-02-18 20:33:23 · 48 阅读 · 0 评论 -
【剑指27】二叉树的镜像
文章目录方法一:递归后序遍历二叉树:时间O(n),空间O(n)方法二:借助栈先序遍历:时间O(n),空间O(n)方法三:借助队列层序遍历:时间O(n),空间O(n)方法一:递归后序遍历二叉树:时间O(n),空间O(n)/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int原创 2021-02-18 20:05:09 · 51 阅读 · 0 评论 -
【剑指26】树的子结构
文章目录方法一:先序判断每个节点:时间O(mn),空间O(m) m>n方法一:先序判断每个节点:时间O(mn),空间O(m) m>n题解:先序遍历二叉树A判断二叉树A节点node为根,二叉树B能否构成子结构,接口 isSubStructure() 先序遍历二叉树 A ,recur() 判断是不是子结构/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeN原创 2021-02-18 19:59:59 · 50 阅读 · 0 评论 -
【剑指24】反转链表
文章目录方法一:递归:时间O(n),空间O(n)方法二:迭代:时间O(n),空间O(1)方法一:递归:时间O(n),空间O(n)题解:回溯的时候将每个节点的下一个节点的指针域指向当前节点,并且把当前节点的next指针域设置为空当前节点next指针域不为空则进行递归,否则返回当前节点在回溯的时候将每个节点的next->next指向当前节点,并把当前节点next置空防止环形链表返回新的头结点/** * Definition for singly-linked list. * stru原创 2021-02-09 18:31:41 · 41 阅读 · 0 评论 -
【剑指22】链表中倒数第K个节点
文章目录方法一:快慢指针:时间O(n),空间O(1)方法一:快慢指针:时间O(n),空间O(1)题解:双指针,一个指针先走k步,然后两个指针同时向后移动,直到快指针为空,返回慢指针k大于链表的总结点数:返回头结点,快指针跑到了空/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x),原创 2021-02-09 16:17:53 · 43 阅读 · 0 评论 -
【剑指21】调整数组顺序使奇数位于偶数前面
文章目录方法一:首尾指针:时间O(n),空间O(1)方法二:快慢指针:时间O(n),空间O(1)类似题目方法一:首尾指针:时间O(n),空间O(1)题解:交换首部的偶数和尾部的奇数,然后让指针一个++,一个 - -,直到left >= right首部指针:只要 left 的数值为奇数,则一直++尾部指针:只要 right 的数值为偶数,则一直 - -class Solution {public: vector<int> exchange(vector<int&原创 2021-02-08 15:41:04 · 59 阅读 · 0 评论 -
【剑指20】表示数值的字符串
文章目录方法一:依次判断并标记:时间O(n),空间O(1)方法一:依次判断并标记:时间O(n),空间O(1)题解:数值有4种情况,即:正负号、小数点 、指数、数字,分情况处理这四种状态正负号:只能出现在数值首,或者 e 后一个位置小数点:只能出现在 e 的前面,且只能出现一次指数:指数的两侧必须有数字,即指数前后都要有数字,且只能出现一次数字:可以在任何位置出现其他:数字中其他出现则直接返回falseclass Solution {public: bool isNumber(s原创 2021-02-08 15:22:18 · 60 阅读 · 0 评论 -
【剑指18】删除链表节点
文章目录方法一:双指针:时间O(n),空间O(1)方法二:单指针:时间O(n),空间O(1)方法一:双指针:时间O(n),空间O(1)题解:用两个指针,pre 代表前驱节点,cur 表示当前节点。遍历链表如果 cur 值和 target 相等则让 cur 的前驱指向cur 的后继class Solution {public: ListNode* deleteNode(ListNode* head, int val) { 1.双指针 if (h原创 2021-01-16 16:50:41 · 41 阅读 · 0 评论 -
【剑指17】打印从1到最大的n位数
文章目录方法一:不考虑大数溢出:时间O(10n10^n10n),空间O(1)方法二:大数打印:时间O(10n10^n10n),空间O(10n10^n10n)方法一:不考虑大数溢出:时间O(10n10^n10n),空间O(1)题解:不考虑大数溢出 int 的情况class Solution {public: vector<int> printNumbers(int n) { int count = pow(10, n); vector<原创 2021-01-16 16:33:00 · 45 阅读 · 0 评论 -
【剑指16】数值的整数次方
文章目录方法一:快速幂:时间O(logn),空间O(1)方法一:快速幂:时间O(logn),空间O(1)题解:注重细节:0 和 1 的 n 次方都是0和1正常循环求幂的时间复杂度是O(n)二分法求幂可将时间降到O(logn)class Solution {public: double myPow(double x, int n) { if (x == 0.0 || x == 1.0) return x; long e原创 2021-01-16 16:14:28 · 44 阅读 · 0 评论 -
【剑指15】二进制中1的个数
文章目录方法一:位运算:时间O(1),空间O(1)方法一:位运算:时间O(1),空间O(1)题解:利用位运算每 n & (n - 1) 一次,可清除一次二进位地位的1class Solution {public: int hammingWeight(uint32_t n) { // 1.位运算 int res = 0; while (n) { res++;原创 2021-01-12 15:53:39 · 56 阅读 · 0 评论 -
【剑指13】机器人的运动范围
文章目录方法一:深度优先搜索:时间O(mn),空间O(mn)方法一:深度优先搜索:时间O(mn),空间O(mn)题解:模拟机器人的走向,每次都先判断能否到达目的位置,如果能到达,则标记该位置表示已经来过机器人从左上角[0, 0]开始走,意味着 dfs 可以只向右和下走class Solution {public: int res = 0; bool isCorrect(int x, int y, int k) { int count = 0;原创 2021-01-12 15:44:25 · 55 阅读 · 0 评论 -
【剑指14】剪绳子
文章目录剪绳子I贪心:时间O(1),空间O(1)剪绳子II:贪心 + 快速幂:时间O(logn),空间O(1)剪绳子I贪心:时间O(1),空间O(1)题解:一般情况下绳子分的段数越多,乘积也就越大为了使乘积更大,分得段数 3 越多,结果也就越大若以每段长 3 分得剩下长度为1,则把最后一节分成 2 * 2 > 1 * 3class Solution {public: int cuttingRope(int n) { // 1.数学,贪心原创 2021-01-11 17:33:58 · 47 阅读 · 0 评论 -
【剑指12】矩阵中的路径
文章目录方法一:模拟遍历矩阵:时间O(3k3^{k}3kmn),空间O(mn)方法一:模拟遍历矩阵:时间O(3k3^{k}3kmn),空间O(mn)k:字符串长度,m、n:矩阵的长和宽时间复杂度: 每个位置都有三个方向可以走(不能走回头路),因此时间 3k3^{k}3k。矩阵的每个位置都应该检查是否正确,因此时间 m*n题解:遍历整个矩阵,若满足条件则模拟走上下左右位置,看是否有路径满足不能走回头路,因此每次都把board中走过的路标记一下,在回溯的时候应该恢复上次状态注意结束条件c原创 2021-01-11 17:23:17 · 49 阅读 · 1 评论 -
【剑指11】旋转数组的最小值
文章目录方法一:二分查找:时间O(logn),空间O(1)方法一:二分查找:时间O(logn),空间O(1)题解:比较 mid 值和 right 的值分三种情况若num[mid] < num[right],则 mid 和 right 处于同一个递增序列,也就是可以忽略右半区间。让right = mid,注意这里不能确定mid 处是不是最小值,因此不能是right = mid - 1若num[left] > num[right],则 mid 和 right 处于不同递增区间,[left原创 2021-01-10 21:51:50 · 57 阅读 · 0 评论 -
【剑指10】斐波那契数列、青蛙跳台问题
文章目录方法一:动态规划:时间O(n),空间O(1)方法一:动态规划:时间O(n),空间O(1)题解:fib(n) = fib(n - 1) + fib(n - 2),而fib(0) = 0,fib(1) = 1class Solution {public: int fib(int n) { // 1.动态规划:dp[i] = dp[i - 1] + dp[i - 2] // 其中 dp[0] = 0, dp[1] = 1 if (原创 2021-01-10 21:34:12 · 77 阅读 · 0 评论 -
【剑指09】用两个栈实现队列
文章目录方法一:辅助栈:时间O(n),空间O(n)方法一:辅助栈:时间O(n),空间O(n)题解:用两个栈,一个栈用来插入数据,另一个栈用来删除数据class CQueue {public: stack<int> stack1; stack<int> stack2; CQueue() { while (!stack1.empty()) { stack1.pop(); }原创 2021-01-09 22:33:57 · 49 阅读 · 0 评论 -
【剑指07】重建二叉树
文章目录方法一:递归:时间O(n),空间O(n)方法一:递归:时间O(n),空间O(n)题解:根据先序中的索引,找到中序中的对应位置k建立节点,划分k位置之前是节点的左树,k位置之后是节点的右树结束条件:索引到头 或者 left == right这里用了一个map键值对保存中序的值和索引,map的查找时间复杂度为O(1)class Solution {public: int index = 0; // 先序的索引 unordered_map<int, int&g原创 2021-01-09 22:30:46 · 44 阅读 · 0 评论 -
【剑指06】从头到尾打印链表
文章目录方法一:辅助栈:时间O(n),空间O(n)方法二:递归:时间O(n),空间O(n)方法三:逆置链表:时间O(n),空间O(n)方法一:辅助栈:时间O(n),空间O(n)题解:利用栈的先进后出特性,先遍历链表进行入栈,随后出栈并把元素放入数组class Solution {public: vector<int> reversePrint(ListNode* head) { if (head == NULL) return vector<原创 2021-01-08 14:58:59 · 43 阅读 · 0 评论 -
【剑指05】替换空格
文章目录方法一:新建空间:时间O(n),空间O(n)方法二:原地修改:时间O(n),空间O(1)方法一:新建空间:时间O(n),空间O(n)题解:新建一个字符串,从头开始遍历原始字符串,遇到 ’ ',则添加 %20class Solution {public: string replaceSpace(string s) { string res; for (auto i : s) { if (i == ' ')原创 2021-01-08 14:50:00 · 55 阅读 · 0 评论 -
【剑指04】二维数组中的查找
文章目录方法一:线性查找:时间O(m+n),空间O(1)方法一:线性查找:时间O(m+n),空间O(1)解题:通过题目描述,我们可以发现把数组左旋45°之后,类似二叉搜索树的特性,最顶部左边的数比其小,右边的数都比其大。因此通过这一特性,我们从右上角或者左下角开始查找,建议从左下角开始,可以少一步数组为空的判定class Solution {public: bool findNumberIn2DArray(vector<vector<int>>& matri原创 2021-01-07 15:48:51 · 74 阅读 · 0 评论 -
【剑指03】数组中重复的数字
文章目录方法一:hash表:时间O(n),空间O(n)方法二:原地交换:时间O(n),空间O(1)方法一:hash表:时间O(n),空间O(n)解题:统计每个数的出现次数,如果遇到表里已经有的数字,则直接返回class Solution {public: int findRepeatNumber(vector<int>& nums) { unordered_map<int, bool> board; for (int原创 2021-01-07 15:42:07 · 52 阅读 · 0 评论