算法训练营
Leonadoice
不会翻译的程序员不是一个好的设计师。欢迎关注个人微信公众号:Ice的小窝。
展开
-
啃算法 | 快速排序
一天一个小主题总结 复杂度 原理。一定可以的!原创 2021-03-17 08:20:13 · 258 阅读 · 0 评论 -
二叉树专题
各种树操作遍历平衡树搜索树dfs bfs二叉树的定义struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) {}};满二叉树:只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,深度为k,有2^k-1个节点。完全二叉树:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到原创 2020-12-20 09:21:46 · 134 阅读 · 0 评论 -
剑指 Offer 68 | II. 二叉树的最近公共祖先
题目:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x的深度尽可能大(一个节点也可以是它自己的祖先)。”例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]示例 1:输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1输出: 3解释: 节点 5原创 2020-12-17 14:45:19 · 181 阅读 · 0 评论 -
剑指 Offer 68 | I. 二叉搜索树的最近公共祖先
题目给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x的深度尽可能大(一个节点也可以是它自己的祖先)。”例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]示例 1:输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8输出: 6 解释:原创 2020-12-17 14:19:33 · 130 阅读 · 0 评论 -
剑指offer | 55 - II. 平衡二叉树
题目输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。示例 1:给定二叉树 [3,9,20,null,null,15,7] 3 / \ 9 20 / \ 15 7返回 true 。示例 2:给定二叉树 [1,2,2,3,3,null,null,4,4] 1 / \ 2 2 / \ 3 3 / \ 4原创 2020-12-13 18:55:40 · 108 阅读 · 0 评论 -
剑指offer | 55 - I. 二叉树的深度
题目内容:输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。例如:给定二叉树 [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7返回它的最大深度 3 。提示:节点总数 <= 10000方法一: DFS深搜也就是树的后续遍历,找到左右子树最深的那个的深度再加上root的1就可以。DFS往往用递归或者栈来实现。/**原创 2020-12-12 22:42:40 · 119 阅读 · 0 评论 -
剑指offer | 54. 二叉搜索树的第k大节点
题目内容:给定一棵二叉搜索树,请找出其中第k大的节点。示例 1:输入: root = [3,1,4,null,2], k = 1 3 / \ 1 4 \ 2输出: 4示例 2:输入: root = [5,3,6,2,4,null,null,1], k = 3 5 / \ 3 6 / \ 2 4 / 1输出: 4限制:1 ≤ k ≤ 二叉搜索树元素个数思路:首先二叉搜索树的特点是:二叉原创 2020-12-12 22:00:15 · 108 阅读 · 0 评论 -
剑指offer | 53.在排序数组中查找数字 I
题目统计一个数字在排序数组中出现的次数。示例 1:输入: nums = [5,7,7,8,8,10], target = 8输出: 2示例 2:输入: nums = [5,7,7,8,8,10], target = 6输出: 0限制:0 <= 数组长度 <= 50000代码:class Solution {public: int search(vector<int>& nums, int target) { int原创 2020-12-24 18:38:16 · 113 阅读 · 1 评论 -
剑指offer |52. 两个链表的第一个公共节点
题目:输入两个链表,找出它们的第一个公共节点。如下面的两个链表:输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3输出:Reference of the node with value = 8输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交原创 2020-12-23 07:35:07 · 117 阅读 · 0 评论 -
剑指offer | 45. 把数组排成最小的数
题目:输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。示例 1:输入: [10,2]输出: "102"示例 2:输入: [3,30,34,5,9]输出: "3033459"提示: 0 < nums.length <= 100说明: 输出结果可能非常大,所以你需要返回一个字符串而不是整数 拼接起来的数字可能会有前导 0,最后结果不需要去掉前导 0思路:先比较最高位,按最高位从小到大排如果最高位相同原创 2020-12-23 07:57:21 · 190 阅读 · 0 评论 -
剑指offer | 39. 数组中出现次数超过一半的数字
题目数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。你可以假设数组是非空的,并且给定的数组总是存在多数元素。示例 1:输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]输出: 2限制:1 <= 数组长度 <= 50000方法一:排序把数组从小到大(或者从大到小)排序,然后直接输出中间哪个数必定是要找的数,因为数字如果出现的次数要超过数组长度的一半,那么,排序之后最中间的那个数必定是我们要找的。class Solution {publi原创 2020-12-31 09:29:11 · 135 阅读 · 0 评论 -
剑指 Offer | 37. 序列化二叉树
题目:请实现两个函数,分别用来序列化和反序列化二叉树。示例:你可以将以下二叉树: 1 / \ 2 3 / \ 4 5序列化为 "[1,2,3,null,null,4,5]"思路:层序遍历BFS,层序遍历且需要把空的节点也记录下来,保证整个序列是唯一的,且能反向恢复成唯一的二叉树。/** * Definition for a binary tree node. * struct TreeNode { * int val;原创 2020-12-17 08:45:48 · 77 阅读 · 0 评论 -
剑指offer | 34. 二叉树中和为某一值的路径
题目内容:输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。示例:给定如下二叉树,以及目标和 sum = 22, 5 / \ 4 8 / / \ 11 13 4 / \ / \ 7 2 5 1返回:[ [5,4,11,2原创 2020-12-17 07:56:38 · 177 阅读 · 0 评论 -
剑指offer | 32 - III. 从上到下打印二叉树 III
题目:请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。例如:给定二叉树: [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7返回其层次遍历结果:[ [3], [20,9], [15,7]]提示:节点总数 <= 1000思路: 双边队列,前取后放,后取前放class Soluti原创 2020-12-13 22:38:17 · 80 阅读 · 0 评论 -
剑指offer | 32 - II. 从上到下打印二叉树 II
题目内容从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。例如:给定二叉树: [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7返回其层次遍历结果:[ [3], [9,20], [15,7]]提示:节点总数 <= 1000方法一:DFSclass Solution {public: vector<vector<int>>原创 2020-12-13 21:46:13 · 105 阅读 · 0 评论 -
剑指offer | 32 - I. 从上到下打印二叉树
题目:从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。例如:给定二叉树: [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7返回:[3,9,20,15,7] 提示:节点总数 <= 1000思路: 借助queue进行层次遍历。/** * Definition for a binary tree node. * struct TreeNode { * int原创 2020-12-13 19:20:38 · 116 阅读 · 0 评论 -
剑指 Offer | 31. 栈的压入、弹出序列
题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列{1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2}就不可能是该压栈序列的弹出序列。示例 1:输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1]输出:true解释:我们可以按以下顺序执行:push(1), push(2), push(3), p原创 2021-01-02 10:03:51 · 121 阅读 · 0 评论 -
剑指 Offer | 30. 包含min函数的栈
题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是O(1)。示例:MinStack minStack = new MinStack();minStack.push(-2);minStack.push(0);minStack.push(-3);minStack.min(); --> 返回 -3.minStack.pop();minStack.top(); --> 返回原创 2021-01-02 09:31:56 · 111 阅读 · 0 评论 -
剑指 Offer | 29. 顺时针打印矩阵
题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。示例 1:输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]输出:[1,2,3,6,9,8,7,4,5]示例 2:输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]输出:[1,2,3,4,8,12,11,10,9,5,6,7]限制:0 <= matrix.length <= 1000 <= matrix[i].length <原创 2021-01-02 08:54:03 · 113 阅读 · 0 评论 -
剑指offer | 28. 对称的二叉树
题目内容:请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。例如,二叉树 [1,2,2,3,4,4,3] 是对称的。 1 / \ 2 2 / \ / \3 4 4 3但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的: 1 / \ 2 2 \ \ 3 3示例 1:输入:root = [1,2,2,3,4,4,3]输出:true示例 2:输原创 2020-12-10 10:16:02 · 93 阅读 · 0 评论 -
剑指offer | 27. 二叉树的镜像
题目内容请完成一个函数,输入一个二叉树,该函数输出它的镜像。例如输入: 4 / \ 2 7 / \ / \1 3 6 9镜像输出: 4 / \ 7 2 / \ / \9 6 3 1示例 1:输入:root = [4,2,7,1,3,6,9]输出:[4,7,2,9,6,3,1]方法:递归交换左右子树/** * Definition for a binary tree node. *原创 2020-12-09 09:28:07 · 100 阅读 · 0 评论 -
剑指offer | 26. 树的子结构
题目内容:输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)B是A的子结构, 即 A中有出现和B相同的结构和节点值。例如:给定的树 A: 3 / \ 4 5 / \ 1 2给定的树 B: 4 / 1返回 true,因为 B 与 A 的一个子树拥有相同的结构和节点值。示例 1:输入:A = [1,2,3], B = [3,1]输出:false示例 2:输入:A = [3,4,5,1,2],原创 2020-12-09 08:51:47 · 109 阅读 · 0 评论 -
剑指offer | 25. 合并两个排序的链表
题目内容:输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。示例1:输入:1->2->4, 1->3->4输出:1->1->2->3->4->4限制:0 <= 链表长度 <= 1000方法1:迭代mark:第一遍想的时候不知道定义的头节点应该指向谁,就卡住了,看了题解发现其实只要随便定义一个头节点就可以,到时候返回头节点的next就是答案了(自己脑子还是太死板了)注意边界问题 就是l1,l原创 2020-12-08 08:33:38 · 82 阅读 · 0 评论 -
剑指offer | 24. 反转链表
题目内容:定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。示例:输入: 1->2->3->4->5->NULL输出: 5->4->3->2->1->NULL方法一:双指针迭代两个指针一前一后移动,后面的指针不断讲链表后面结点的指针反向,直到结束。时间复杂度O(N):遍历链表使用线性大小时间空间复杂度O(1):变量pre和cur使用常熟大小额外空间。class Solution {public:原创 2020-12-08 08:06:53 · 135 阅读 · 0 评论 -
剑指offer | 22.链表中倒数第k个节点
题目内容:输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如,一个链表有6个节点,从头节点开始,它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个节点是值为4的节点。示例:给定一个链表: 1->2->3->4->5, 和 k = 2.返回链表 4->5.思路我一开始想的是链表没办法统计参考:一文搞定常见的链表问题 (欢迎交流(这个题解写得太妙了,基本总结了所有链表可能的考题!)原创 2020-12-07 20:48:03 · 98 阅读 · 0 评论 -
剑指offer | 21.调整数组顺序使奇数位于偶数前面
题目内容:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。示例:输入:nums = [1,2,3,4]输出:[1,3,2,4] 注:[3,1,2,4] 也是正确的答案之一。提示:1 <= nums.length <= 500001 <= nums[i] <= 10000思路:双指针,头尾同时遍历,将从前往后遍历到的第一个偶数与从后向前遍历到的第一个奇数交换,然后重复上述动作,直到两指针相原创 2020-12-07 19:09:22 · 90 阅读 · 0 评论 -
剑指offer | 20.表示数值的字符串
题目:请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、“5e2”、"-123"、“3.1416”、"-1E-16"、“0123"都表示数值,但"12e”、“1a3.14”、“1.2.3”、"±5"及"12e+5.4"都不是。思路: 这题有点繁琐,而且容易考虑不全,于是参考:题解-C++逐字符检查用四个变量区分状态:hasNum,hasOp,hasE,hasDot代码结构如下:1.while循环1号--略去前置空格2.while循环2号--逐字符操作原创 2021-01-01 15:54:41 · 152 阅读 · 0 评论 -
剑指offer | 19. 正则表达式匹配
题目内容:请实现一个函数用来匹配包含’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但与"aa.a"和"ab*a"均不匹配。示例 1:输入:s = "aa"p = "a"输出: false解释: "a" 无法匹配 "aa" 整个字符串。示例 2:输入:s = "aa"p = "a*"输出: true解释:原创 2020-12-06 08:17:59 · 145 阅读 · 0 评论 -
剑指offer | 18.删除链表的节点
题目内容:给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。返回删除后的链表的头节点。注意:此题对比原题有改动示例 1:输入: head = [4,5,1,9], val = 5输出: [4,1,9]解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.示例 2:输入: head = [4,5,1,9], val = 1输出: [4,5,9]解释: 给定你链表中值为 1 的第三个节点,那么在调用了原创 2020-12-05 07:43:51 · 134 阅读 · 0 评论 -
剑指offer | 17. 打印从1到最大的n位数
题目内容:输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。示例 1:输入: n = 1输出: [1,2,3,4,5,6,7,8,9]说明:用返回一个整数列表来代替打印n 为正整数方法一:由观察可以得出,不超过n位数就是指不超过10n10^n10n,比如n=3,那么就是不超过1000.又因为题干中返回的是int,所以说嘛不会越界,那么最直观的方法应该是可行的:class Solution {p原创 2020-12-04 08:43:49 · 169 阅读 · 0 评论 -
剑指offer | 16.数值的整数次方
题目内容实现函数double Power(double base, intexponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。示例 1:输入: 2.00000, 10输出: 1024.00000示例 2:输入: 2.10000, 3输出: 9.26100示例 3:输入: 2.00000, -2输出: 0.25000解释: 2-2 = 1/2^2 = 1/4 = 0.25说明:-100.0 < x < 100.0n原创 2020-12-02 07:50:53 · 115 阅读 · 0 评论 -
剑指offer | 15. 二进制中1的个数
题目描述:请实现一个函数,输入一个整数(以二进制串形式),输出该数二进制表示中 1 的个数。例如,把 9 表示成二进制是 1001,有 2 位是1。因此,如果输入 9,则该函数输出 2。示例 1:输入:00000000000000000000000000001011输出:3解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。示例 2:输入:00000000000000000000000010000000输出:1解释:输入的原创 2020-12-01 06:59:09 · 125 阅读 · 0 评论 -
剑指offer | 14. II. 剪绳子
题目内容给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1]…k[m - 1] 。请问 k[0]k[1]…*k[m - 1]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。示例 1:输入: 2输出: 1解释: 2 = 1 + 1,原创 2020-12-01 06:45:05 · 97 阅读 · 0 评论 -
剑指offer | 14. I. 剪绳子
题目给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1]…k[m-1] 。请问 k[0]k[1]…*k[m-1]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。示例 1:输入: 2输出: 1解释: 2 = 1 + 1, 1 × 1 = 1示例 2:输入: 10输出: 36解释: 10 = 3 + 3 + 4, 3 × 3 ×原创 2020-11-26 08:31:29 · 100 阅读 · 0 评论 -
剑指offer | 13. 机器人的运动范围
题目内容地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0]的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格[35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?示例 1:输入:m = 2, n = 3, k = 1输出:3示例 2:输入:原创 2020-11-26 07:20:03 · 172 阅读 · 0 评论 -
剑指offer | 12. 矩阵中的路径
题目内容请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字母用加粗标出)。[["a","b","c","e"],["s","f","c","s"],["a","d","e","e"]]但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个字符b占据了矩阵原创 2020-11-25 08:11:21 · 131 阅读 · 0 评论 -
剑指offer | 11. 旋转数组的最小数字
题目内容把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组[3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。示例 1:输入:[3,4,5,1,2]输出:1示例 2:输入:[2,2,2,0,1]输出:0思路:这题第一反应肯定是二分法,但是一开始我一直在用左端点和mid比较,一直出不来,看了题解才知道应该拿右端点比较,因为题目中说了是单调递增数组旋转,那么要么没有原创 2020-11-25 07:32:25 · 88 阅读 · 0 评论 -
剑指offer | 10.青蛙跳台阶问题
题目内容一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。示例 1:输入:n = 2输出:2示例 2:输入:n = 7输出:21示例 3:输入:n = 0输出:1提示: 0 <= n <= 100思路:斐波那契数列的变体,前面的斐波那契前两个初始值是:f(0)=0,f(1)=1;本题的是f(0)=1,f原创 2020-11-18 09:03:29 · 128 阅读 · 0 评论 -
剑指offer | 10.斐波那契数列
题目内容写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项。斐波那契数列的定义如下:F(0) = 0, F(1) = 1 F(N) = F(N - 1) + F(N - 2), 其中 N > 1.斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。示例 1:输入:n = 2输出:1示例 2:输入:n = 5输出:5提示:原创 2020-11-18 08:31:45 · 177 阅读 · 0 评论 -
剑指offer | 09. 用两个栈实现队列
题目内容用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )示例 1:输入:["CQueue","appendTail","deleteHead","deleteHead"][[],[3],[],[]]输出:[null,null,3,-1]示例 2:输入:["CQueue","deleteHead","appendT原创 2020-11-17 21:39:53 · 133 阅读 · 0 评论