自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(36)
  • 收藏
  • 关注

原创 LeetCode in Python 74/240. Search a 2D Matrix I/II (搜索二维矩阵I/II)

搜索二维矩阵I其实可以转换为搜索一维数组,原因在于,只要先确定搜索的整数应该在哪一行,即可对该行进行二分查找。搜索二维矩阵II中矩阵元素排列方式与I不同,但思想大致相同。

2024-04-26 11:13:08 839

原创 LeetCode in Python 10. Regular Expression Matching (正则表达式匹配)

出现此类情况是因为我们不想选择p[j - 1],即p[j - 1]与对应位置的s[i - 1]不相等(需要注意的是这里的p[j - 1]不等于s[i - 1]包含两种情况,一是两者均为小写字母且不等,二是p[j - 1]不为‘.’)的小写字母或字符‘.’,则直接与s中对应位置比较即可,若相同则dp[i][j] == dp[i - 1][j - 1],这里需要注意字符‘.’可匹配任意字符,可归为p[i][j]==s[i][i]这类情况。出现此种情况是因为p[j - 1]与对应位置的s[i - 1]相等。

2024-04-25 11:32:21 1306 1

原创 LeetCode in Python 1718. Construct the Lexicographically Largest Valid Sequence (构建字典序最大的可行序列)

2)注意回溯过程,若dfs(cur + 1)返回false表明之前放置的一对数字出现问题,这时需要回溯到放置之前的状态,即res[cur] = res[gap + cur] = -1。= -1,则进入对下一个位置的判断。四是在放入两个数字时要判断第二个数字的位置是否越界,若未越界且未曾被修改(即可用为空)才能放置到该位置。一是边界条件,如果cur已经判断到末尾,则表明已经找到可行序列,返回true即可。三是对于gap的赋值,需要分情况讨论,因为1只在序列中出现一次,而其余数字出现两次。

2024-04-23 15:02:02 189

原创 基于知识图谱的智能问答系项目——导入数据

代码来源:@每天都要机器学习。

2024-04-22 21:32:40 223

原创 LeetCode in Python 72. Edit Distance (编辑距离)

编辑距离的基本思想很直观,即不断比较两个单词每个位置的元素,若相同则比较下一个,若不同则需要考虑从插入、删除、替换三种方法中选择一个最优的策略。涉及最优策略笔者最先想到的即是动态规划的思想,将两个单词的位置对应放在矩阵中即可将其转化为类似求解最小路径和的问题。1)cost为记录最少操作数的二维数组,若word2为空,word1变为word2需要删除word1中所有字符,即操作数为len(word1)。图1 编辑距离输入输出示意图。

2024-04-22 19:06:35 728

原创 LeetCode in Python 69. Sqrt(x) (x的平方根)

本文利用二分思想,给出一种时间复杂度为O(logn)的代码实现,当x=10000时时间复杂度O(logn)远小于O(但其时间复杂度为O(n),或是想到遍历0~M即可,其中M = x // 2,将时间复杂度降至O(1)只需注意一点,当m**2 < x时要及时更新res,因为可能不存在。求x的平方根,第一想法可能是遍历0~x,求其平方,找到。图1 平方根输入输出示例图。的情况,这是返回的应该是。

2024-04-22 16:06:35 178

原创 LeetCode in Python 48. Rotate Image/Matrix (旋转图像/矩阵)

1)外层循环控制需要转的大圈圈数,内层循环控制每一圈需要转的小圈圈数,大小圈数的解释见图2,例如n=4,需要循环n // 2 = 2大圈,其中黄色循环箭头为第一大圈,绿色循环箭头为第二大圈。对于第一大圈,5->11->16->15->5为一小圈,同理1->10->12->13->1、9->7->14->2->9各为一小圈。3)为了使算法空间复杂度为O(1),只需将每一次循环的左上角元素保存下来,接着采用逆向循环的顺序调整元素,最后将左上角元素归位即可,如此便无需重新开辟一个O() 空间来保存原始矩阵。

2024-04-22 15:23:52 1130

原创 LeetCode in Python 200. Number of islands (岛屿数量)

岛屿数量既可以用深度优先搜索也可以用广度优先搜索解决,本文给出两种方法的代码实现。示例:图1 岛屿数量输入输出示意图。

2024-04-19 17:11:12 619

原创 LeetCode in Python 55. Jump Game (跳跃游戏)

从最后一个位置开始往前跳,如果前一个位置(i)+前一个位置可以跳的最大长度(nums[i])>=goal,表明可以从前一个位置跳到目标位置。如此一来,即可将目标位置更新为前一个位置,如此往复,直到goal==0,即可以跳到第一个位置,表明完成跳跃游戏,反之不能。),为此,本文采用贪心策略,从最后一个下标开始逆着向前走,若能跳到第一个元素则表明可以完成跳跃游戏,反之不能。跳跃游戏的游戏规则比较简单,若单纯枚举所有的跳法以判断是否能到达最后一个下标需要的时间复杂度为O(图1 跳跃游戏输入输出示例。

2024-04-19 11:01:49 439

原创 LeetCode in Python 509. Fibonacci Number (斐波那契数)

斐波那契数实现方式有多种方法,最容易理解的为递归法,也可使用动态规划降低时间复杂度,本文给出递归法和动态规划两种方法的代码实现。1)求f(n)需要计算n-1次,例如计算f(4),需要计算f(4)、f(3)和f(2),故循环n次后取保存上一次计算结果的n1。图1 斐波那契数输入输出示例。

2024-04-18 16:35:33 186

原创 LeetCode in Python 704. Binary Search (二分查找)

1)当nums[mid] > target时表明target在[0, mid]区间内,故将右指针r移至mid-1,同理当nums[mid] < target时表明target在[mid, len(nums) - 1]区间内,将左指针移至mid+1,直到不满足循环l<=r时退出或找到target的位置返回下标指针。2)注意while循环的条件l<=r,若为l<r,则当数组只有一个元素时将无法返回正确下标位置。二分查找是一种高效的查询方法,时间复杂度为O(nlogn),本文给出二分查找的代码实现。

2024-04-18 11:27:57 293

原创 LeetCode in Python 1338. Reduce Array Size to The Half (数组大小减半)

1)Counter函数用于计数,对存储结构(本题中为数组,可适用于所有存储结构)内元素技术,返回一个字典,key为元素,value为元素数量。ps:区别于count()函数仅能记录元素数量。3)count.most_common()函数返回一个包含count中n个最大数目的元素的列表,元素若有相同数目将选择出现更早的元素。数组大小减半思路简单,主要是熟悉python中collections.Counter的用法,采用贪心策略即可。2)n记录当前选取的元素个数,ans记录当前已选取元素种类。

2024-04-18 11:02:57 606

原创 LeetCode 179 in Python. Largest Number (最大数)

寻找最大数的逻辑简单,但如何对两数比较组成更大的整数是一个重点。例如示例2中如何区分3与30谁放在前面以及3与34谁放在前面是一个难点,本文通过采用functools中的自定义排序规则cmp_to_key()来判断上述情况,并给出代码实现。3)compare函数设置排序规则选择能组成更大整数的排序形式,返回-1为不变,返回1为相反。图1 最大数输入输出示例。

2024-04-16 11:34:07 432

原创 LeetCode 64 in Python. Minimum Path Sum (最小路径和)

1)res为一个储存当前位置最小路径和的二元数组,举例说明,如图2所示,res[2][2] = 1 + min(res[3][2], res[2][3])。解法二则利用动态规划的思想,从终点开始不断更新到达终点上一步的最小路径和,从而找到起点到终点的最小路径和,这种解法的时间复杂度为O(n)。注意:res数组规模为(row + 1) * (col + 1),但数组下标从0开始,在遍历时需注意下标取值范围。2)最终从起点到终点的最小路径和即储存在res[0][0]中。图1 最小路径和示例。

2024-04-14 17:31:16 874

原创 LeetCode 1 in Python. Two Sum (两数之和)

两数之和算法思想很简单,即找到nums[i]和nums[j]==target-(nums[i])返回[I, j ]即可。问题在于,简单的两层遍历循环时间复杂度为O(),而通过构建一个hash表就可将时间复杂度降至O(n)。本文给出两种方法的代码实现。方法二:哈希表(时间复杂度为O(n))方法一:枚举(时间复杂度为为O(图1 两数之和输入输出示例图。

2024-04-14 11:28:50 140 1

原创 LeetCode 217/219/220 in Python. Contains Duplicate (存在重复元素)

leecode217、219和220均是解决是否存在重复元素问题,在此统一依次解答。示例:图1 Leecode 217示例解释:1) 设置一个集合list,根据集合不重复存储相同元素的特性进而判断数组是否有重复元素。

2024-04-13 20:00:44 1284 1

原创 Sorting Algorithms in Python (排序算法)

本篇文章主要介绍几种经典排序算法:冒泡排序、快速排序、选择排序、堆排序、插入排序、希尔排序、归并排序、桶排序和基数排序。并给出用python实现的算法代码。

2024-04-10 21:38:06 1226 1

原创 LeetCode in Python 215. Kth Largest Element in an Array (数组中的第k个最大元素)

数组中第k个最大元素,最简单的做法就是先给数组排序然后寻找倒数第k个最大元素,但为进一步降低算法的时间复杂度,可以采用快速查找的方法确定元素,即采用快速排序的“哨兵划分”和递归思想。1)pivot即为哨兵,将数组中>、<、=哨兵的元素存储到三个数组中,通过判断第k大元素落在哪个数组确定快速查找递归的下一个数组是谁。2)着重注意对k的判断以及递归中的k值即可。图1 输入输出示例图。

2024-04-08 10:56:19 177

原创 LeetCode in Python 300. Longest Increasing Subsequence (最长递增子序列)

求最长递增子序列是深度优先搜索(DFS)的一种应用,有两种比较好的方法可以解决。简而言之,按顺序判断数组每个元素,如果该元素大于已加入的所有元素,则直接append到LIST数组结尾,反之替换数组中不影响数组长度的最大元素。举例说明,如上图,遍历至5,可替换上一步加入的8且数组长度依然为3。2)接着开始动态规划,如果该元素大于其下一个元素,即表明下一个元素可以成为递增子序列的一员跟该元素放在一起。此时,规划的对象就由该元素移至下一个元素,直至不满足判断条件。LIST初始值为1,即该数组元素本身作为序列值。

2024-04-05 19:53:39 841 1

原创 LeetCode in Python 4. Median of Two Sorted Arrays (寻找两个正序数组的中位数)

重复直至找到一个合适的m1使得从两个数组中取出的元素为合并两数组后最小的half个元素。4)对于数组奇偶元素个数的分开判断,如果数组有奇数个元素,则中位数应该是取完half(此half为向下取的整数)后两个数组右中位数的最小值,举例说明,有13个元素,half=6,中位数应为两数组合并后第7个元素,而第7个元素来源只能是取完half个数后两数组的右中位数中的一个,即right1和right2中的一个,根据正序排列的顺序,小的在前大的在后,故第7个元素应为min(right1, right2)。

2024-04-05 16:34:21 1201 1

原创 LeetCode in Python 88. Merge Sorted Array (合并两个有序数组)

第一种,重新开辟一个数组空间,大小为O(m+n),另外需要三个指针分别指向两个有序数组和新开辟的数组,依次判断两个数组内元素大小,不断更新指针即可。第二种,无需单独开辟空间,在第一个数组(该数组空间足够存放两个数组总长的数据)内进行操作,仍然需要三个指针,可从尾部开始合并,因此需要尾指针和分别指向两数组的指针。2)当出现nums1第一个元素大于nums2第一个元素时,在nums1遍历完后nums2还有剩余,由于两个数组均为升序排列,故只需把nums2剩余的n个数组元素挪到nums1前n个元素即可。

2024-04-04 11:32:57 334 1

原创 LeetCode in Python 23. Merge K Sorted Lists (合并k个升序链表)

合并k个升序链表有两种方法,第一种是每次从各个链表中取出最小值然后将该链表当前指针移至该链表该值的next重复直到所有链表的当前指针均指向None(即遍历结束)。这种方法的时间复杂度为O(kn)其中k为链表数,n为所有链表最长长度。第二种即采用分治思想,两两链表合并直至合并完所有链表。这种方法只需合并logk次,时间复杂度为O(nlogk)。本文主要给出方法二的代码实现。1)注意返回None的两种情况,区别if not xxx与xxx is None。对i+1的判断即防止下标溢出。图1 输入输出示意图。

2024-04-03 21:24:25 365 1

原创 LeetCode in Python 19. Remove Nth Node From End of List (删除链表的倒数第N个结点)

返回链表倒数第N个结点有两种方法,第一种方法是遍历两次链表,第一次遍历求链表长度,第二次遍历找到倒数第N个结点前一个结点,最后将该结点的next结点更换至next结点的next结点即可。第二种方法则只需要遍历一次链表,但需要设置两个指针,一前一后,指针间隔即为n,当后指针为None时说明已至链尾,此后修改前指针的next指向即可。本文推荐用解法二,但附上两种解法代码。range(n)为一个半开半闭区间,故这里firsr指针要想先走n步需要range(n+1)图1 删除链表结点前后对比。

2024-04-03 15:49:25 222 1

原创 LeetCode in Python 225. Implement Stack using Queues (用队列实现栈)

注意这里的n一定是添加新元素之前的(即只需移走push之前队列原有的元素,将新元素放至队头),否则新加入元素也会移到最后,出现错误。用队列实现栈即利用队列先进先出(FIFO)的特性实现栈先进后出(FILO)的要求。1)双队列的实现思想跟单队列一样,只是前者通过一个辅助队列放入新加入的元素,再将原队列的元素一个个挪到辅助队列中,随后交换,不断重复。1)单队列的实现方法即先添加新的队列元素,然后将最后一个队列元素前的元素按序移到最后一个队列元素后即可。图1 输入输出示意图。

2024-04-03 11:23:06 361 1

原创 LeetCode in Python 232. Implement Queue using Stacks (用栈实现队列)

但值得注意的是python中None, False, 空字符串"", 0, 空列表[], 空字典{}, 空元组()都相当于False,所以区别不当会影响判断。if not xxx若成立,即代表xxxx等于None, False, 空字符串"", 0, 空列表[], 空字典{}, 空元组()用栈实现队列即通过栈先进后出(FILO)的特性实现队列先进先出(FIFO)的功能。if xxx is None若成立,则只能说明xxx为None这一种情况。1)区分if not xxx 和 if xxx is None。

2024-04-02 21:47:49 293 1

原创 Implementation of Queue using Arrays in Python (使用数组实现队列)

首先需要定一个一个动态数组,其中包括数组的增加、删除、查找、判空、判满以及重置空间操作。其次,使用动态数组大类定义序列队列,队列作为动态数组的一个子类,继承父类的各个方法,通过调用动态数组的内部函数实现队列的出入队等操作。注意range(a, b)取值范围为[a, b),range(a, b, -1)同样取值为一个半开半闭区间,从a到b倒着取值,如range(5, 0, -1)取值为[5, 4, 3, 2, 1]。这里可以在数组最后一个元素后增加元素,因为在增加元素前会对动态数组进行判满操作,若满则扩容。

2024-04-02 17:02:25 703 1

原创 Depth First Search in Python (深度优先搜索)

深度优先搜索简称深搜或DFS,与广搜结点先进先出的顺序不同,深搜结点进入方式为先进后出,故需要采用栈结构存储结点。深搜和广搜一样可以解决大范围查找问题,除此之外,深搜主要用于求子序列或子集问题。3)与广搜不同的是,深搜在没有特殊条件要求下无需记录父结点,所以没有设置parent字典储存各结点的父结点。2)同样设置flag作为标记集合,用于标记该结点是否已被遍历。4)需要注意深搜的答案不唯一,取决于每次先从栈中弹出的结点。1)与广搜使用队列不同,深搜的搜索方式需要栈结构配合。

2024-03-26 20:51:32 305

原创 Breadth First Search in Python (宽度/广度优先搜索)

宽搜/广搜简称BFS,Dijkstra单源最短路径算法和Prim最小生成树算法均使用广搜的思想,从一点出发向外辐射直至遍历所有结点。本文主要总结在图和树(特殊的图)上的广搜。2)parent字典用于记录某结点的父结点,方便路径回溯;flag为一个集合,用于标记已经遍历过的结点(该图为无向图);s为起始结点,v为终止结点。1)此处手动输入了示例1,若实际图过大或复杂可以设置相应类。图的广度优先搜索(图源为AI AX AT)图的广度优先搜索(图源为AI AX AT)1)树的广度优先搜索本质上即为树的层次遍历。

2024-03-26 16:43:52 240

原创 LeetCode in Python 124. Binary Tree Maximum Path Sum (二叉树的最大路径和)

2)result记录目前为止最大的路径和,但若回溯至上一层结点需要返回的是该结点和选取的一支子树(路径和最大的一支子树)的路径和。如此反复,不断比较当前最大路径和与回溯到上一层结点的最大路径和,从而找到全树的最大路径和(该路径可不经过根结点)。2)返回上一层结点时,该结点只能选择一支子树的值,即路径是一条不回头的路。1)只有一个根节点且为负数,此时返回的应该是该结点值而非0。3)可以不经过根节点,选择整棵树中最大路径和即可。(上述三种情况对应以下例图,图源来自花花酱)

2024-03-25 21:39:45 106

原创 LeetCode in Python 226. Invert Binary Tree (翻转二叉树)

迭代法仍是需要一个队列存储各层结点,分别对每层每个节点的左右子结点一一左右对调,直到所有结点均为叶子结点,对调结束。翻转二叉树即将每层结点左右对调,仍然可以采用递归和迭代两种方法。

2024-03-25 17:21:50 245 1

原创 LeetCode in Python 101. Symmetric Tree (对称二叉树)

对称二叉树即判断该二叉树是否为轴对称树,左右呈镜像。有两种解法,递归法和迭代法,递归法较为简单,容易理解。迭代法可帮助理解二叉树结构及相关操作。迭代法主要思想即展开每一层结点,判断是否为回文数。需要注意的是,每展开一次需要重置next_queue和level。

2024-03-23 16:44:55 215 1

原创 LeetCode in Python 102. Binary Tree Level Order Traversal (二叉树的层序遍历)

二叉树层序遍历,即按照层数从左到右依次遍历结点。需要注意的是,不同于前中后序遍历,层序遍历不仅需要层与层之间的结点出现顺序,还需同一层内结点的先后顺序。此时,我们需要一个能记录当前层所有结点的队列,其次我们需要根据本层的结点记录下一层的结点队列,最后我们需要在遍历每一层时记录每一层每一个结点的情况。需要区别queue和level,前者存储当前层数所有即将遍历的结点,而后者则针对每一层每一个结点的累积记录,每遍历完一层中的某个结点,就将该结点记录到level中方便result的添加。

2024-03-23 13:05:46 193 2

原创 LeetCode in Python 144. Binary Tree Postorder Traversal (二叉树的后序遍历)

二叉树后序遍历相较于前序和中序要相对复杂一些,主要原因在于,前序遍历只需特别关注根结点,中序遍历需要额外考虑左结点,而后序遍历不仅要记录左结点,根结点还需不断注意是否有右结点。这个循环表示:弹出了栈顶结点后需要判断已弹出的这个结点是否为现在栈顶元素的右孩子。若是,表明当前栈顶元素也已无左右孩子,可以弹出。当无左子树左结点时,要记录最后一个左结点的右结点,即栈顶元素的右结点。否则说明该栈顶元素为一个根节点,已无左右孩子,只需弹出自己。如果此时最后一个左结点有右孩子,则需把右孩子也压入栈中。

2024-03-21 19:37:49 121

原创 LeetCode in Python 94. Binary Tree Inorder Traversal (二叉树的中序遍历)

其中需要注意的是前序遍历的迭代过程仅仅关注根结点即可,即不断锁定新的根节点位置,因为前序遍历的过程为根左右,而中序遍历则需要先把二叉树所有节点的左结点先压入栈中,然后再逐一弹出左结点和根结点,最后是右结点。这一步是提醒将一个结点弹出后要判断此结点有无右结点,若有继续压入右结点的左子结点,若没有直接跳出while root,重新从stack最顶端弹出一个新的结点开始新一轮迭代。二是root在迭代过程中到了一个空的左指针,即无左结点的时候跳出循环,此时所有结点的左结点全部压入栈中,可以开始pop操作了;

2024-03-21 17:23:42 382 1

原创 LeetCode in Python 144. Binary Tree Preorder Traversal (二叉树的前序遍历)

前序遍历的递归原理简单,即根据根左右的顺序,先按照前序遍历的方式遍历根结点,再遍历跟节点的左子树,最后遍历根结点的右子树,此过程通过换结点不断调用遍历函数即可。而迭代方法则相对复杂一点,考虑到要保留每一步回溯的根结点,需要设置一个栈结构,通过不断压入弹出结点实现对每个结点的左右结点的遍历。需要注意的是,出栈原则为先进后出,故需要先压入右结点再压入左结点其次是根结点,才能在弹出时实现先输出根结点接着左结点最后右结点的顺序。

2024-03-21 16:29:54 165

原创 LeetCode in Python 114. Flatten Binary Tree to Linked List (二叉树展开为链表)

展开(2, 3, 4)的过程为先观察2号节点有无左子树,若有,先将2号节点右子树转移至左子树的最右端(若无右子树,则转移空节点),后将2号节点左子树转移至2号节点右子树,从而实现根节点左子树的展开变换。接着,将1号节点右子树转移至2号节点的最右端,即将(5, 6)节点转移至2号节点最右端,然后将2号节点及其子树转移至根节点右端,完成展开,注意返回右左根实现递归。return部分,递归时先返回右子树再返回左子树才能实现逐层递归,直到只剩根节点,递归结束。空间复杂度为O(1)。

2024-03-21 15:25:52 200

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除