自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 KMP算法:找出字符串中第一个匹配项的下标

其中 j 表示最长前缀的下一个下标,例如模式串 s = "aabaac" ,当 j 等于2时,表示此时最长前缀为"aa",所以 j 也可以理解成此时最长前缀的长度。首先要知道前缀表的任务是当前位置匹配失败,找到之前已经匹配上的位置,再重新匹配,此也意味着在某个字符失配时,前缀表会告诉你下一步匹配中,模式串应该跳到哪个位置。当二者不相等时,我们让 j 回溯到与s[j]==s[i]的下标处。KMP主要应用在字符串匹配上。根据next数组的定义,我们可以直接得出next[0]的值为0,j 我们初始化为0。

2023-11-01 23:42:07 135

原创 动态规划--整数拆分

动态规划解决的经典类型题目之一。首先要明确dp数组的含义,再找出状态转移方程并初始化,迭代下去即可得出解。),并使这些整数的乘积最大化。你可以获得的最大乘积。

2023-11-30 23:18:24 242 1

原创 动态规划--不同路径 II

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。本题相对与不同路径那道题其实异曲同工,无非是多了一些条件判断罢了。现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?网格的左上角 (起始点在下图中标记为 “Start” )。1. 向右 -> 向右 -> 向下 -> 向下。2. 向下 -> 向下 -> 向右 -> 向右。我们可以运用滚动数组,降低空间复杂度。3x3 网格的正中间有一个障碍物。网格中的障碍物和空位置分别用。

2023-11-26 00:20:53 61 1

原创 动态规划--不同路径

想要求dp[i][j],只能有两个方向来推导出来,即dp[i - 1][j] 和 dp[i][j - 1],那么很自然,dp[i][j] = dp[i - 1][j] + dp[i][j - 1],因为dp[i][j]只有这两个方向过来。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角。网格的左上角 (起始点在下图中标记为 “Start” )。可以使用滚动数组,将空间复杂度从O(n^2)降到O(n)。时间复杂度达到O(2^(m+n)),显然超时了。暴力算法就是深搜了,把每条路径都遍历一遍。

2023-11-25 23:58:26 58

原创 动态规划--使用最小花费爬楼梯

一旦你支付此费用,即可选择向上爬一个或者两个台阶。- 支付 1 ,向上爬两个台阶,到达下标为 2 的台阶。- 支付 1 ,向上爬两个台阶,到达下标为 4 的台阶。- 支付 1 ,向上爬两个台阶,到达下标为 6 的台阶。- 支付 1 ,向上爬一个台阶,到达下标为 7 的台阶。- 支付 1 ,向上爬两个台阶,到达下标为 9 的台阶。- 支付 15 ,向上爬两个台阶,到达楼梯顶部。- 支付 1 ,向上爬一个台阶,到达楼梯顶部。你将从下标为 1 的台阶开始。你将从下标为 0 的台阶开始。

2023-11-25 22:32:00 58

原创 贪心算法--加油站

题目描述在一条环路上有n个加油站,其中第i个加油站有汽油gas[i]升。你有一辆油箱容量无限的的汽车,从第i个加油站开往第i+1个加油站需要消耗汽油cost[i]升。你从其中的一个加油站出发,开始时油箱为空。给定两个整数数组gas和cost,如果你可以按顺序绕环路行驶一周,则返回出发时加油站的编号,否则返回-1。如果存在解,则它是的。3从 3 号加油站(索引为 3 处)出发,可获得 4 升汽油。此时油箱有 = 0 + 4 = 4 升汽油。

2023-11-18 22:24:01 72

原创 贪心算法--K 次取反后最大化的数组和

如果遍历完数组后,我们的遍历次数K依然大于0的话,此时我们数组里全都大于或等于0,我们只需根据。本题其实很容易看出是用贪心算法,但别小瞧这道题目,没有点小技巧,很容易写出所谓的“屎山代码”。选择下标 (1, 2, 2) ,nums 变为 [3,1,0,2]。选择下标 (1, 4) ,nums 变为 [2,3,-1,5,4]。选择下标 1 ,nums 变为 [4,-2,3]。以这种方式修改数组后,返回数组。可以多次选择同一个下标。

2023-11-15 23:26:43 38

原创 贪心算法--最大子数和

从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小。,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。这道题有多种方式解决,比如贪心、动态规划、分治等,在这里我提供。连续子数组 [4,-1,2,1] 的和最大,为 6。是数组中的一个连续部分。

2023-11-15 22:36:51 37

原创 贪心算法--分发饼干

贪心思路:大饼干既可以喂给胃口小的的孩子,也可以喂给胃口大的孩子,要满足更多孩子胃口,我们必须充分利用饼干,大饼干优先喂给胃口大的孩子,或者说小饼干优先喂给胃口小的孩子。假设你是一位很棒的家长,想要给你的孩子们一些小饼干。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。,这是能让孩子们满足胃口的饼干的最小尺寸;你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。

2023-11-15 22:19:27 27

原创 构造二叉树-----从中序与后序遍历序列构造二叉树

就是以后序数组的最后一个元素为切割点,先切中序数组,根据中序数组,反过来再切后序数组。一层一层切下去,每次后序数组最后一个元素就是节点元素。要我们说里面最难的当属第四步和第五步了,我们要一开始就统一标准,到底是怎么去切割数组,我这里统一按照。如果不为空,那么取后序数组最后一个元素作为节点元素。找到后序数组最后一个元素在中序数组的位置,作为切割点。如果数组大小为零的话,说明是空节点了,直接返回。切割中序数组,切成中序左数组和中序右数组。切割后序数组,切成后序左数组和后序右数组。是二叉树的中序遍历,

2023-11-09 19:35:52 29

原创 二叉树与回溯----二叉树的所有路径

在这道题目中将第一次涉及到回溯,因为我们要把路径记录下来,在遍历过程中需要利用回溯来回退一个路径再进入另一个路径。题目需要求从根节点到叶子的路径,所以需要前序遍历,这样才方便让父节点指向孩子节点,找到对应的路径。回溯算法的具体详解将在后续推出,这里可以大概了解一下模板。,返回所有从根节点到叶子节点的路径。给你一个二叉树的根节点。是指没有子节点的节点。

2023-11-09 19:24:10 34

原创 二叉树与递归----对称二叉树

二叉树系列的题目一般比较抽象,即使知道算法,代码实现起来也不容易,而递归却能带来不可思议的效果。对于二叉树是否对称,我们要比较的是根节点的左子树与右子树是不是相互翻转的,理解这一点就知道了。,如果全都满足条件,那么该二叉树就是对称二叉树。,所以在递归遍历的过程中,也是要同时遍历两棵树。我们递归函数里传入左右子树的根节点,如果。给你一个二叉树的根节点。, 检查它是否轴对称。

2023-11-09 19:14:25 43

原创 二叉树的层序遍历

二叉树的各种遍历方式其实是有模板的,这次我们来看看二叉树的层序遍历的模板是怎样的吧。我们只需借助一个队列,借助队列的先进先出的特点,就能达到层序遍历的效果。(即逐层地,从左到右访问所有节点)。

2023-11-09 18:55:06 30

原创 二叉树的非递归遍历

我们这里很巧妙,我们让左孩子先入栈,右孩子后入栈,这样我们的遍历顺序就是 “中右左” 了,诶,好像并没有达到后序遍历的要求啊。因为中序遍历很特殊,前序遍历的时候,我们处理节点的时机和访问节点的时机是一致的,而中序遍历的时候,我们先访问的是中间节点,但我们此时还不能处理它,我们必须得先去处理其左孩子之后,才能轮到本身。,并把沿途的节点存入栈中,这样才符合我们“左中右” 的遍历顺序,栈的意义其实是记录了我们遍历时的路径。我们知道递归的本质其实是调用了系统栈,我们手动提供一个栈就能模拟这个过程了。

2023-11-04 18:00:16 25

原创 TopK经典问题:前 K 个高频元素

求解TopK问题,我们能想到的最直接的方式就是排序,但是,如果数据量非常大,排序就不太可取了因为数据很可能不能一下子全部加载到内存当中,也就是说,内存装不了这么大的数据,最佳的办法就是用堆来解决。如果使用大顶堆的话,当堆内元素的数量超过K个的时候,我们再插入数据,我们只能把堆内最大的元素给踢出了,这显然达不到我们的目的,所以我们应该使用小顶堆。从小到大排列就是小顶堆,从大到小排就是大顶堆。我们可以先用哈希表统计出不同元素的频率,然后找出频率在前K名的元素,这其实就演化成TopK问题了。什么TopK问题呢?

2023-11-04 17:24:45 62 4

原创 滑动窗口最大值

每次窗口移动的时候,调用que.pop(滑动窗口中移除元素的数值),que.push(滑动窗口添加元素的数值),然后que.front()就返回我们要的最大值。这道题暴力解法大部分人都会,遍历每一个起点,在每个窗口内寻求最大值就好了,但时间复杂度达到了O(n*k),在leetcode上提交会运行超时,如何降低时间复杂度呢?保持如上规则,每次窗口移动的时候,队列里面始终维持单调递减的状态,只要调用que.front()就可以返回当前窗口的最大值。的滑动窗口从数组的最左侧移动到数组的最右侧。

2023-11-04 17:06:19 23

原创 逆波兰表达式求值(后缀表达式求值)

我们习惯看到的表达式都是中缀表达式,因为符合我们的习惯,但是中缀表达式对于计算机来说就不是很友好了,而前缀表达式和后缀表达式对计算机来说是非常友好的。要求解前缀表达式或者后缀表达式,我们可以借助栈来做。该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6。返回一个表示表达式值的整数。最后栈中的数字便是我们最终的结果了。

2023-11-04 16:51:46 36

原创 反转字符串中的单词

由于有的编程语言可能有类似于split之类的函数用来分隔单词或者删除空格,但我们平时做题过程应减少库函数的使用,毕竟,我们的目的是锻炼思维,而不是背诵各种函数,如果你对这个函数了然于心,那可以直接使用该函数。这里顺便提一下,有的编程语言中的字符串是常量,我们不能直接修改,比如Java,所以不同语言的实现方式会略有不同。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。我们如果直接将整个字符串都进行翻转,则每个单词也被翻转了,所以,我们只需再对每个单词再进行一次翻转就好了。

2023-11-01 22:34:35 26

原创 四数之和

那道题很相似,我们依然利用双指针。这次我们先固定前两个数,假设分别为x和y, 然后在之后的数据中寻找和为(-x-y)的两个数。请你找出并返回满足下述全部条件且。

2023-10-29 00:02:32 39 1

原创 三数之和

题目描述给你一个整数数组nums,判断是否存在三元组满足i!= ji!= k且j!= k,同时还满足。请你返回所有和为0且不重复的三元组。答案中不可以包含重复的三元组。不同的三元组是 [-1,0,1] 和 [-1,-1,2]。注意,输出的顺序和三元组的顺序并不重要。思路。

2023-10-28 23:54:20 28

原创 赎金信

第一个思路就是暴力枚举了,两层for循环,不断去寻找,时间复杂度为O(n^2),试着降低时间复杂度。因为题目说只有小写字母,那可以采用空间换取时间的哈希策略,用一个长度为26的数组来记录magazine里字母出现的次数。然后再用ransomNote去验证这个数组是否包含了ransomNote所需要的所有字母。依然是数组在哈希法中的应用。

2023-10-28 23:44:24 27

原创 四数相加 II

对于 A 和 B,我们使用二重循环对它们进行遍历,得到所有 A[i]+B[j] 的值并存入哈希映射中。对于哈希映射中的每个键值对,每个键表示一种 A[i]+B[j],对应的值为 A[i]+B[j] 出现的次数。当遍历到 C[k]+D[l] 时,如果 −C[k]−D[l] 出现在哈希映射中,那么将 −C[k]−D[l] 对应的值累加进答案中。我们可以将四个数组分成两部分,假设四个数组分别为A,B,C,D。最终即可得到满足 A[i]+B[j]+C[k]+D[l]=0 的四元组数目。,请你计算有多少个元组。

2023-10-28 23:39:11 26

原创 两数之和

这道题是leetcode第一题,是我们“梦开始的地方”。很明显暴力的解法是两层for循环查找,时间复杂度是O(n^2)。我们每遍历到一个数,设其为 i, 然后在哈希表中查找是否存在值target - i,如果存在,那我们便找到了满足题目要求的答案,如果不存在,则将i 为Key, 当前下标为Value这一键值对存入哈希表。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。因为 nums[0] + nums[1] == 9 ,返回 [0, 1]。整数,并返回它们的数组下标。

2023-10-28 23:28:36 19

原创 快乐数

意识到这一点这道题就就解决一大半了。我们使用哈希法,来判断这个sum是否重复出现,如果重复了就是return false, 否则一直找到sum为1为止。这道题目看上去貌似一道数学问题,其实并不是!编写一个算法来判断一个数。

2023-10-28 23:18:32 20

原创 两个数组的交集

这道题用暴力的解法时间复杂度是O(n^2),那来看看使用哈希法进一步优化。由于题目中限定了数据的范围,所以我们可以利用数组当做哈希表。而且如果哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费。输出结果中的每个元素一定是。[4,9] 也是可通过的。

2023-10-28 23:13:00 28

原创 哈希表理论基础

哈希表hashtable(key,value) 的做法其实很简单,通过hashCode把Key转化为数值,一般hashcode是通过特定编码方式,可以将其他数据格式转化为不同的数值,这样就把Key转化为一个具体的数字了。然后该数字通过一个固定的算法函数,将其转换成一个下标,最后将value存储在该下标的数组空间里。该算法即所谓的哈希函数。而当使用哈希表进行查询的时候,就是再次使用哈希函数将key转换为对应的数组下标,并定位到该空间获取value,如此一来,就可以充分利用到数组的定位性能进行数据定位。

2023-10-28 22:10:25 25

原创 环形链表 II

我们可以先用快慢指针判断是否有环,具体做法是维护一快一慢两个指针,慢指针每次移动一步,快指针每次移动两步,如果两指针最终相遇,则必定有环。假设存在环,让慢指针移动到链表的起点,快指针依然在相遇点,然后两指针同时并同速向后移动,再次相遇处就是入环口。可以画图并结合数学方法证明,这里略过。链表中有一个环,其尾部连接到第二个节点。,返回链表开始入环的第一个节点。返回索引为 1 的链表节点。给定一个链表的头节点。如果链表无环,则返回。

2023-10-27 21:32:13 91 1

原创 面试题 02.07. 链表相交

一种普遍的思路是先遍历两个链表,分别求出其长度,再维护两个指针,让表长较长的那个指针先走两长之差的长度,表长较短的那个指针从头开始,然后两指针同时前进,直至相遇或者遍历结束。但这是面试题,普通解法肯定不是面试官想要的,我们能只不求出表长判断是否相交吗?关键思路是让两表等长。设表长分别为m和n,m!n,我们维护两个指针指向两条链表,当其中一个链表遍历结束,我们让该指针指向另一链表,继续进行遍历,另一指针也是相同操作,最后两指针必然会相等(相遇或者同时为空)。,请你找出并返回两个单链表相交的起始节点。

2023-10-27 21:21:12 30 1

原创 删除链表的倒数第 N 个结点

一看这道题目,大家很快就能想到我先遍历一遍链表求出表长,假设表长为m,然后再遍历链表找到正数第m-n个,最后进行删除操作不就好了吗?诚然这是一种解法,但这道题是一道面试题,面试官要的肯定不是这个解法。时间复杂度我们是不可能减少了,至少得是o(n),那我们能只遍历一次链表就删除该节点吗?我们只需维护一前一后两个指针,姑且称之为fast和slow,然后让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。给你一个链表,删除链表的倒数第。个结点,并且返回链表的头结点。

2023-10-27 21:02:55 29 1

原创 两两交换链表中的节点

解决这道题目,有两种普遍解法,一种是递归解法,另一种是非递归解法,递归解法代码更简洁,但效率不如非递归解法。但两种解法核心思路都是一样,都是根据题意改变指针的指向,一般画画图很快就能想出来。你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。Python3非递归版本。

2023-10-27 20:52:15 26 1

原创 翻转链表

如果额外定义一个链表,其实是对资源的浪费,我们只需更改箭头的指向就行。那如何更改箭头的指向呢?我们只需维护两个指针,姑且称为pre和cur,cur指向当前待翻转的子链表首节点,pre指向翻转之后的链表(中间可能需要临时指针保存地址),然后进行翻转,直至翻转结束。输入: 1->2->3->4->5->NULL。输出: 5->4->3->2->1->NULL。

2023-10-27 20:42:34 30 1

原创 设计链表

这道题在leetcode上描述地很长,我用自己的话概括了一遍。要写好链表类型的题目,得先对链表了如指掌,自己实现一个链表类是很有必要的。废话不多说,直接看代码。类,该类封装了一个链表,能够进行常用的增删改查的操作。

2023-10-27 20:32:38 28 1

原创 移除链表元素

很基础的一道链表类型的题目,虽然简单,但能帮助我们更好地理解链表的特性。解决这道题,我们只需维护一前一后两个指针就好了,但难点是对首节点的操作,如果我们把首节点删了该怎么办呢?避免这种问题我们只需新增一个虚拟节点,就不需要管首节点的“死活”了,做到首节点和其他节点“一视同仁”。示例 1: 输入:head = [1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5]示例 3: 输入:head = [7,7,7,7], val = 7 输出:[]删除链表中等于给定值 val 的所有节点。

2023-10-26 22:25:54 35 1

原创 螺旋矩阵||

本题其实并没有涉及什么算法,核心就是模拟,但却十分考验对代码的掌控能力,稍微不注意可能就会写出所谓的“屎山代码”,写这种题需要我们抓住循环不变量,时刻保持思路的清晰。输入: 3 输出: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ]给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按。顺序螺旋排列的正方形矩阵。

2023-10-26 18:11:31 25

原创 长度最小的子数组

其实,这是一道典型的滑动窗口类型的经典例题,核心还是利用双指针,维护一左一右两个指针,两指针之间可看成一个窗口,不断扩大窗口,满足条件之后再逐步缩小窗口,直到遍历结束。ps:不要以为while循环里再放一个while循环就以为是O(n^2)啊,其实是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)。给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的。子数组,并返回其长度。

2023-10-26 17:41:00 20

原创 有序数组的平方

看到题目第一时间的想法就是先求出每一个元素的平方,再进行排序,但时间复杂度会达到0(nlogn),有没有更快的解法呢?注意到原数组是有序的,我们知道平方最大的数肯定在数组的两端,而不可能会出现在中间,利用这个想法,可以巧妙利用数指针,每次在两端取平方较大的数值,并更新指针。排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按。

2023-10-26 17:29:14 25

原创 移除元素

示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并。

2023-10-26 17:19:00 25

原创 二分查找

这些都是使用二分法的前提条件。二分法查找元素的写法大体可分为两种,一种是左闭右闭区间,一种是左闭右开区间,本文给出第一种的写法。拓展:如果数组中含有重复元素,那该如何使用二分查找法呢?,因为如果有重复元素,使用二分查找法返回的元素下标。,如果目标值存在返回下标,否则返回。个元素有序的(升序)整型数组。,同时题目还强调数组中。

2023-10-25 18:42:07 109 4

原创 初来乍到,请多关照

一个来自上海海洋大学的编程爱好者和算法爱好者,从今日起我将不定期更新撰写以算法为主的题解,题目以leetcode上的题目为主,希望和大家一起学习,相互勉励,学术不精,还望海涵!

2023-10-24 14:47:51 83 3

空空如也

空空如也

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

TA关注的人

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