![](https://img-blog.csdnimg.cn/20201018231020103.jpg?x-oss-process=image/resize,m_fixed,h_224,w_224)
算法模型
文章平均质量分 61
记录经典算法的训练之路
星尘 StarDust
Datawhale团队成员,开源贡献者,一个不断寻找自我的追光者。
展开
-
剑指 Offer 14- II. 剪绳子 II -- 贪心算法
0 题目描述leetcode原题链接:剑指 Offer 14- II. 剪绳子 II1 贪心算法此题与 面试题14- I. 剪绳子 主体等价,唯一不同在于本题目涉及 “大数越界情况下的求余问题” 。本题用动态规划比较复杂,还是要看贪心。核心思路是:尽可能把绳子分成长度为3的小段,这样乘积最大。具体证明请参考后面的参考资料链接。求解步骤如下:如果 n == 2,返回1,如果 n == 3,返回2,两个可以合并成n小于4的时候返回n - 1如果 n == 4,返回4如果 n > 4,分原创 2021-07-11 12:24:27 · 438 阅读 · 0 评论 -
剑指 Offer 14- I. 剪绳子 -- 动态规划
0 题目描述leetcode原题链接:剑指 Offer 14- I. 剪绳子1 动态规划想要求长度为n的绳子剪掉后的最大乘积,可以从前面比n小的绳子转移而来用一个dp数组记录从0到n长度的绳子剪掉后的最大乘积,也就是dp[i]表示长度为i的绳子剪成m段后的最大乘积,初始化dp[2] = 1先把绳子剪掉第一段(长度为j),如果只剪掉长度为1,对最后的乘积无任何增益,所以从长度为2开始剪剪了第一段后,剩下(i - j)长度可以剪也可以不剪。如果不剪的话长度乘积即为j * (i - j);如果剪的原创 2021-07-11 12:14:07 · 458 阅读 · 0 评论 -
剑指 Offer 18. 删除链表的节点 -- 双指针
0 题目描述leetcode原题链接:剑指 Offer 18. 删除链表的节点1 双指针解法删除值为 val 的节点分需为两步:定位节点、修改引用。定位节点: 遍历链表,直到 head.val == val 时跳出,即可定位目标节点。修改引用: 设节点 cur 的前驱节点为 pre ,后继节点为 cur.next ;则执行 pre.next = cur.next ,即可实现删除 cur 节点。# Definition for singly-linked list.# class Lis原创 2021-07-11 11:58:36 · 434 阅读 · 0 评论 -
剑指 Offer 07. 重建二叉树 -- 递归
0 题目描述leetcode原题链接:剑指 Offer 07. 重建二叉树1 递归解法二叉树前序遍历的顺序为:先遍历根节点;随后递归地遍历左子树;最后递归地遍历右子树。二叉树中序遍历的顺序为:先递归地遍历左子树;随后遍历根节点;最后递归地遍历右子树。在「递归」地遍历某个子树的过程中,是将这颗子树看成一颗全新的树,按照上述的顺序进行遍历。挖掘「前序遍历」和「中序遍历」的性质,就可以得出本题的做法。# Definition for a binary t原创 2021-07-11 11:42:09 · 160 阅读 · 0 评论 -
剑指 Offer 55 - II. 平衡二叉树 -- 递归
0 题目描述leetcode原题链接:剑指 Offer 55 - II. 平衡二叉树1 自顶向下的递归这道题中的平衡二叉树的定义是:二叉树的每个节点的左右子树的高度差的绝对值不超过 11,则二叉树是平衡二叉树。根据定义,一棵二叉树是平衡二叉树,当且仅当其所有子树也都是平衡二叉树,因此可以使用递归的方式判断二叉树是不是平衡二叉树,递归的顺序可以是自顶向下或者自底向上。这道题是计算二叉树深度的扩展,定义计算二叉树深度函数maxDepth(),即可判断二叉树是否平衡。具体做法类似于二叉树的前序遍历,即对原创 2021-01-07 22:42:19 · 249 阅读 · 0 评论 -
leetcode 路径总和 -- 递归
0 题目描述leetcode原题链接:112. 路径总和1 递归解法假定从根节点到当前节点的值之和为 val,我们可以将这个大问题转化为一个小问题:是否存在从当前节点的子节点到叶子的路径,满足其路径和为 sum - val。不难发现这满足递归的性质,若当前节点就是叶子节点,那么我们直接判断 sum 是否等于 val 即可(因为路径和已经确定,就是当前节点的值,我们只需要判断该路径和是否满足条件)。若当前节点不是叶子节点,我们只需要递归地询问它的子节点是否能满足条件即可。# Definition原创 2021-01-07 15:29:29 · 180 阅读 · 0 评论 -
剑指 Offer 27. 二叉树的镜像 -- 递归
0 题目描述leetcode原题链接:剑指 Offer 27. 二叉树的镜像1 递归算法根据二叉树镜像的定义, 考虑递归遍历 dfs\mathrm{dfs}dfs 二叉树,交换每个节点的左 / 右子节点, 即可生成 二叉树的镜像。递归解析:终止条件:当节点 root 为空时 (即越过叶节点),则返回 null ;递推工作:初始化节点 tmp,t m p,tmp, 用于暂存 root 的左子节点;开启递归 右子节点 mirrorTree(root.right),并将返回值作为 root原创 2021-01-07 15:02:04 · 194 阅读 · 0 评论 -
leectode 合并二叉树 -- 递归
0 题目描述leetcode原题链接:617. 合并二叉树1 递归解法可以使用深度优先搜索合并两个二叉树。从根节点开始同时遍历两个二叉树,并将对应的节点进行合并。两个二叉树的对应节点可能存在以下三种情况,对于每种情况使用不同的合并方式。如果两个二叉树的对应节点都为空,则合并后的二叉树的对应节点也为空;如果两个二叉树的对应节点只有一个为空,则合并后的二叉树的对应节点为其中的非空节点;如果两个二叉树的对应节点都不为空,则合并后的二叉树的对应节点的值为两个二叉树的对应节点的值之和,此时需要显性合并原创 2021-01-07 11:59:13 · 164 阅读 · 0 评论 -
剑指 Offer 28. 对称的二叉树 -- 递归
0 题目描述leetcode原题链接:剑指 Offer 28. 对称的二叉树1 递归解法在这里插入代码片参考资料原创 2021-01-07 10:04:23 · 181 阅读 · 2 评论 -
剑指 Offer 68 - I. 二叉搜索树的最近公共祖先 -- 递归
0 题目描述leetcode原题链接:剑指 Offer 68 - I. 二叉搜索树的最近公共祖先1 递归解法# Definition for a binary tree node.# class TreeNode:# def __init__(self, x):# self.val = x# self.left = None# self.right = Noneclass Solution: def lowestCommo原创 2021-01-06 22:45:15 · 216 阅读 · 8 评论 -
leetcode 二叉树的最小深度 -- 递归
0 题目描述leetcode原题链接:111. 二叉树的最小深度1 递归解法叶子节点的定义是左孩子和右孩子都为 null 时叫做叶子节点。当 root 节点为 null 时,返回 0。当 root 节点左右孩子都为空时,返回 1。当 root 节点左右孩子有一个为空时,返回不为空的孩子节点的深度。当 root 节点左右孩子都不为空时,返回左右孩子较小深度的节点值。# Definition for a binary tree node.# class TreeNode:# def原创 2021-01-06 19:51:26 · 206 阅读 · 0 评论 -
剑指 Offer 68 - II. 二叉树的最近公共祖先 -- 递归
0 题目描述leetcode原题链接:剑指 Offer 68 - II. 二叉树的最近公共祖先1 递归解法代码思路:递归查询两个节点p q,如果某个节点等于节点p或节点q,则返回该节点的值给父节点。如果当前节点的左右子树分别包括p和q节点,那么这个节点必然是所求的解。如果当前节点有一个子树的返回值为p或q节点,则返回该值。(告诉父节点有一个节点存在其子树中)如果当前节点的两个子树返回值都为空,则返回空指针。# Definition for a binary tree node.# cla原创 2021-01-06 15:31:20 · 199 阅读 · 0 评论 -
leetcode 两两交换链表中的节点 -- 递归
0 题目描述leetcode原题链接:24. 两两交换链表中的节点1 递归解法# Definition for singly-linked list.# class ListNode:# def __init__(self, val=0, next=None):# self.val = val# self.next = nextclass Solution: def swapPairs(self, head: ListNode) ->原创 2021-01-06 11:49:02 · 222 阅读 · 0 评论 -
剑指 Offer 25. 合并两个排序的链表 --递归与双指针解法
0 题目描述leetcode原题链接:剑指 Offer 25. 合并两个排序的链表1 双指针解法# Definition for singly-linked list.# class ListNode:# def __init__(self, x):# self.val = x# self.next = Noneclass Solution: def mergeTwoLists(self, l1: ListNode, l2: ListNode原创 2021-01-05 22:55:41 · 153 阅读 · 0 评论 -
剑指 Offer 55 - I. 二叉树的深度 --后续遍历
0 题目描述leetcode原题链接:剑指 Offer 55 - I. 二叉树的深度1 后续遍历找出 root 的左子树和右子树的深度,然后取其较大的值 +1 即可(因为 root 本身也有一个单位的深度)。后序遍历,也叫深度优先搜索(DFS),往往利用递归或者栈来实现。# Definition for a binary tree node.# class TreeNode:# def __init__(self, x):# self.val = x#原创 2021-01-05 22:24:56 · 199 阅读 · 0 评论 -
剑指 Offer 16. 数值的整数次方 -- 快速幂
0 题目描述leetcode原题:剑指 Offer 16. 数值的整数次方1 快速幂解法快速幂实际上是二分思想的一种应用。二分推导: xn=xn/2×xn/2=(x2)n/2,x^{n}=x^{n / 2} \times x^{n / 2}=\left(x^{2}\right)^{n / 2},xn=xn/2×xn/2=(x2)n/2, 令 n/2n / 2n/2 为整数, 则需要分为奇偶两种情况(设向下取整除 法符号为 " //"/ / "//" ) :∘\circ∘ 当 nnn 为偶数: x原创 2021-01-05 20:15:32 · 249 阅读 · 6 评论 -
排序算法原理总结和Python实现
1 排序算法分类比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。相关概念:稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。空原创 2021-01-01 16:48:05 · 269 阅读 · 2 评论 -
基数排序(Radix Sort)-- 特殊排序算法
1 基数排序(Radix Sort)基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。算法描述取得数组中的最大数,并取得位数;arr为原始数组,从最低位开始取每个位组成radix数组;对radix进行计数排序(利用计数排序适用于小范围数的特点)动图演示代码实现def Radix_sort(nums): if no原创 2021-01-01 16:24:31 · 298 阅读 · 2 评论 -
桶排序(Bucket sort) -- 特殊排序算法
1 桶排序(Bucket sort)桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。桶排序 (Bucket sort)的工作的原理:假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排)。算法描述设置一个定量的数组当作空桶;遍历输入数据,并且把数据一个一个放到对应的桶里去;对每个不是空的桶进行排序;从不是空的桶里把排好序的数据拼接起来。图片演示代码实现def buck原创 2021-01-01 16:14:40 · 500 阅读 · 4 评论 -
计数排序(Counting Sort)-- 特殊排序算法
1 计数排序(Counting Sort)计数排序不是基于比较的排序算法,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。 作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。算法描述找出待排序的数组中最大和最小的元素;统计数组中每个值为i的元素出现的次数,存入数组C的第i项;对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加);反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1。动图演示代码实现def原创 2020-12-31 23:32:37 · 379 阅读 · 2 评论 -
希尔排序(Shell Sort)-- 高级排序算法
1 希尔排序(Shell Sort)1959年Shell发明,第一个突破O(n2)O(n^2)O(n2)的排序算法,是简单插入排序的改进版。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。算法描述先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,具体算法描述:选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;按增量序列个数k,对序列进行k 趟排序;每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子原创 2020-12-31 23:27:48 · 185 阅读 · 0 评论 -
堆排序(Heapsort)-- 高级排序算法
1 堆排序(Heapsort)堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。二叉堆本质上是一种完全二叉树,它分为两个类型:最大堆和最小堆。最大堆任何一个父节点的值,都大于等于它左右孩子节点的值。最小堆任何一个父节点的值,都小于等于它左右孩子节点的值。二叉堆的根节点叫做堆顶。最大堆和最小堆的特点,决定了在最大堆的堆顶是整个堆中的最大元素;最小堆的堆顶是整个堆中的最小元素。算法描述将初始待排序关键字序列(R1,R2….Rn)构建成大顶堆,此堆为初始的无序区;将堆顶元素R[1]原创 2020-12-31 23:21:59 · 307 阅读 · 2 评论 -
归并排序(Merge Sort)-- 高级排序算法
1 归并排序(Merge Sort)归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。算法描述把长度为n的输入序列分成两个长度为n/2的子序列;对这两个子序列分别采用归并排序;将两个排序好的子序列合并成一个最终的排序序列。动图演示代码实现class Solution: d原创 2020-12-31 23:17:45 · 261 阅读 · 2 评论 -
快速排序(Quick Sort)-- 高级排序算法
1 快速排序(Quick Sort)快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。算法描述快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:从数列中挑出一个元素,称为 “基准”(pivot);重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列原创 2020-12-31 23:13:32 · 256 阅读 · 2 评论 -
插入排序(Insertion-Sort)-- 初级排序算法
1 插入排序(Insertion-Sort)插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。算法描述一般来说,插入排序都采用in-place在数组上实现。具体算法描述如下:从第一个元素开始,该元素可以认为已经被排序;取出下一个元素,在已经排序的元素序列中从后向前扫描;如果该元素(已排序)大于新元素,将该元素移到下一位置;重复步骤3,直到找到已排序的元素小于或者等于新元素原创 2020-12-31 23:05:03 · 333 阅读 · 2 评论 -
选择排序(Selection Sort)-- 初级排序算法
1 选择排序(Selection Sort)选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。算法描述n个记录的直接选择排序可经过n-1趟直接选择排序得到有序结果。具体算法描述如下:初始状态:无序区为R[1…n],有序区为空;第i趟排序(i=1,2,3…n-1)开始时,当前有序区和无序区分别为R原创 2020-12-31 23:00:37 · 361 阅读 · 2 评论 -
冒泡排序(Bubble Sort) -- 初级排序算法
1 冒泡排序(Bubble Sort)冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。算法描述比较相邻的元素。如果第一个比第二个大,就交换它们两个;对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;针对所有的元素重复以上的步骤,除了最后一个;重复步原创 2020-12-31 22:53:25 · 342 阅读 · 2 评论 -
剑指 Offer 53 - I. 在排序数组中查找数字 I
0 题目描述leetcode原题链接:剑指 Offer 53 - I. 在排序数组中查找数字 I1 二分查找解题思路:排序数组中的搜索问题,首先想到 二分法 解决。排序数组 nums 中的所有数字 target 形成一个窗口,记窗口的 左 / 右边界 索引分别为 left 和 right ,分别对应窗口左边 / 右边的首个元素。本题要求统计数字 target 的出现次数,可转化为:使用二分法分别找到 左边界 left 和 右边界 right ,易得数字 target 的数量为right−lef原创 2020-12-31 22:43:14 · 146 阅读 · 0 评论 -
Leetcode 在排序数组中查找元素的第一个和最后一个位置 -- 二分查找
0 题目描述leetcode原题链接: 34. 在排序数组中查找元素的第一个和最后一个位置原创 2020-12-31 22:34:17 · 264 阅读 · 0 评论 -
Leetcode 括号的分数 -- 栈
题目描述leetcode: 856. 括号的分数给定一个平衡括号字符串 S,按下述规则计算该字符串的分数:() 得 1 分。AB 得 A + B 分,其中 A 和 B 是平衡括号字符串。(A) 得 2 * A 分,其中 A 是平衡括号字符串。示例 1:输入: “()”输出: 1示例 2:输入: “(())”输出: 2示例 3:输入: “()()”输出: 2示例 4:输入: “(()(()))”输出: 6提示:S 是平衡括号字符串,且只含有 ( 和 ) 。2 <= S.lengt原创 2020-12-27 16:13:05 · 265 阅读 · 0 评论 -
Leetcode 计算质数 -- 埃氏筛、线性筛解析
0 题目描述leetcode原题链接:204. 计数质数1 埃氏筛很直观的思路是我们枚举每个数判断其是不是质数,枚举没有考虑到数与数的关联性,因此难以再继续优化时间复杂度。介绍一个常见的算法, 该算法由希腊数学家厄拉多塞(Eratosthenes ) 提出,称为厄拉多塞筛法,简称埃氏筛。我们考虑这样一个事实:如果 xxx 是质数,那么大于 xxx 的 xxx 的倍数 2x,3x,…2 x, 3 x, \ldots2x,3x,… 一定不是质数,因此我们可以从 这里入手。我们设 isPrime[i原创 2020-12-03 11:34:19 · 444 阅读 · 1 评论 -
Leetcode 环形链表 -- 快慢指针
0 题目描述leetcode原题链接:环形链表最容易想到的是哈希表解法,遍历所有节点,每次遍历到一个节点时,判断该节点此前是否被访问过,但是空间复杂度为O(n)O(n)O(n),有以下更优的解法实现空间复杂度为O(1)O(1)O(1)。1 快慢指针本方法需要读者对「Floyd 判圈算法」(又称龟兔赛跑算法)有所了解。假想「乌龟」和「兔子」在链表上移动,「兔子」跑得快,「乌龟」跑得慢。当「乌龟」和「兔子」从链表上的同一个节点开始移动时,如果该链表中没有环,那么「兔子」将一直处于「乌龟」的前方;原创 2020-11-13 22:37:42 · 217 阅读 · 0 评论 -
Leetcode[数组] 买卖股票的最佳时机 III -- 动态规划
0 题目描述leetcode原题链接:买卖股票的最佳时机 III1 动态规划本题有比较巧妙的解法,和leetcode 121题:买卖股票的最佳时机一题的思路相似。leetcode 121题:买卖股票的最佳时机的代码方案。class Solution: def maxProfit(self, prices: List[int]) -> int: if not prices: return 0 minprice, maxprofit = int(1e9)原创 2020-11-13 21:07:06 · 212 阅读 · 0 评论 -
Leetcode[数组] 删除排序数组中的重复项 -- 双指针法
0 题目描述letcode原题链接:删除排序数组中的重复项 参考资料删除排序数组中的重复项原创 2020-11-04 23:19:42 · 233 阅读 · 2 评论 -
Leetcode[数组] 跳跃游戏 -- 贪心算法
0 题目描述leetcode原题链接:跳跃游戏1 贪心算法思路:尽可能到达最远位置(贪心)如果能到达某个位置,那一定能到达它前面的所有位置。方法:初始化最远位置为 0,然后遍历数组,如果当前位置能到达,并且当前位置+跳数>最远位置,就更新最远位置。如果当前位置比最远位置还要远,直接返回False。class Solution: def canJump(self, nums: List[int]) -> bool: # 最远到达位置 reach原创 2020-11-04 11:25:07 · 852 阅读 · 13 评论 -
Leetcode[数组] 买卖股票的最佳时机 II - 贪心算法
0 题目描述leetcode原题链接:买卖股票的最佳时机 II 1 贪心算法class Solution: def maxProfit(self, prices: List[int]) -> int: maxprofit = 0 for i in range(1,len(prices)): if prices[i] > prices[i-1]: maxprofit = maxprofit +原创 2020-11-03 23:44:14 · 204 阅读 · 0 评论 -
Leetcode[数组] 买卖股票的最佳时机 -- 动态规划
0 题目描述leetcode原题链接:买卖股票的最佳时机1 动态规划假设给定的数组为:[7, 1, 5, 3, 6, 4]如果我们在图表上绘制给定数组中的数字,我们将会得到:我们来假设自己来购买股票。随着时间的推移,每天我们都可以选择出售股票与否。那么,假设在第 i 天,如果我们要在今天卖股票,那么我们能赚多少钱呢?显然,如果我们真的在买卖股票,我们肯定会想:如果我是在历史最低点买的股票就好了!太好了,在题目中,我们只要用一个变量记录一个历史最低价格 minprice,我们就可以假设自己的股原创 2020-11-03 23:22:31 · 283 阅读 · 0 评论 -
Leetcode[数组] 分发饼干 -- 贪心算法
0 题目描述leetcode原题链接:分发饼干1 预排序+双指针利用贪心算法的思想:每次都先满足胃口最小的孩子,直到有效饼干分完,或者小胃口孩子都被满足则停止分发。class Solution: def findContentChildren(self, g: List[int], s: List[int]) -> int: g.sort() s.sort() j = 0 for i in range(len(s)):原创 2020-11-03 22:44:23 · 856 阅读 · 0 评论 -
Leetcode[链表] 反转链表 -- 双指针法
0 题目描述leetcode原题链接:反转链表1 双指针法在这里插入代码片参考资料【反转链表】:双指针,递归,妖魔化的双指针原创 2020-11-02 11:20:50 · 632 阅读 · 1 评论 -
Leetcode[数组] 三数之和 -- 双指针法
0 题目描述leetcode原题链接:三数之和1 排序+双指针解法class Solution: def threeSum(self, nums: List[int]) -> List[List[int]]: n = len(nums) if (not nums or n < 3): return [] nums.sort() res = [] for i in range(n):原创 2020-10-26 14:40:37 · 189 阅读 · 0 评论