刷题之路——中等篇
文章平均质量分 94
记录在牛客网上和LeetCode网上刷中等题的艰辛历程
林先生-1
佛系……但致力于提高文章的文字水平。
展开
-
【刷题之路Ⅱ】LeetCode 739. 每日温度
而当遍历到的温度大于栈顶下标对应的温度时,我们需要连续地将栈顶下标取出,记为index,连续的当前遍历到的温度是否大于index所对应的温度,如果大于就将栈顶下标弹出栈,并将答案数组的answer[index]赋值为i - index。时间复杂度:O(n),n为数组长度,我们需要顺序遍历一遍数组,而每一个下标最多也只有一次出栈和进栈的机会,故总的时间复杂度还是O(n)。空间复杂度:O(n),最坏情况下,n - 1个温度都会累积在栈中,故空间复杂度为O(n)。这样但我们遍历完了数组,我们的答案也就出来了。原创 2023-06-02 15:39:11 · 777 阅读 · 3 评论 -
【刷题之路Ⅱ】LeetCode 1823. 找出游戏的获胜者(约瑟夫问题)
确切地说,从第 i 名小伙伴顺时针移动一位会到达第 (i+1) 名小伙伴的位置,其中 1原创 2023-05-31 13:16:16 · 903 阅读 · 1 评论 -
【刷题之路Ⅱ】迷宫问题升级版——找最短路径
也是因为可能存在多条通路,所以我们在某一条路上头不通或者体力消耗尽了。当我们往回返的时候还需要将这些走过的坐标再改成可通行的坐标,就如下面的这个用红圈圈起来的坐标:我们发现红色和绿色的两条路都经过了这个坐标,而红色的那条是走不通的(体能不够),而如果我们在红色的那条路上往回返的时候没有吧走过的坐标再改成可通行的坐标,那到后面在走绿色那条路的时候就没法在通过红圈圈的这个坐标了,那我们也就找不到可行的通路了。好了,这就是这些就是这一题的重点思路了,剩下的就是代码实现了。原创 2023-05-29 18:43:01 · 1698 阅读 · 1 评论 -
【刷题之路Ⅱ】百度面试题——迷宫问题
我们在GetPath函数里递归调用上下左右四个方向的找通路,如果当前被调用的坐标等于出口坐标就可以返回,而主要上下左右有任何一个方向的递归调用找到了通路就可以返回(同时最重要的是要先判断坐标的有效性)。:因为这里是io型的oj题,所以我们没必要在main函数中最开始就将栈初始化,如果是接口型的oj题,就一定要在main函数中先将栈初始化,不然最多只能过一个测试用例。它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的路线。原创 2023-05-28 20:26:01 · 1124 阅读 · 0 评论 -
【刷题之路Ⅱ】LeetCode 622. 设计循环队列
但又因为单链表的局限性,我们不能直接找到rear的前驱。其实很简单,我们可以使用(rear - 1) + (k + 1)对k + 1取余,正常情况下rear - 1 > 0的时候,加上一个k + 1在对k + 1进行取余其实对结果没什么影响,而当rear - 1= -1时候,加法也就变成了减法,所以就变成了k对k + 1取余,其结果是k,正好是最后一个下标。设计你的循环队列实现。而取队尾这个接口就不同了,因为我们设计的rear是指向队尾元素的下一个元素,所以我么其实要返回的是rear的前一个位置的元素。原创 2023-05-16 18:06:40 · 385 阅读 · 1 评论 -
【刷题之路Ⅱ】LeetCode 475. 供暖器
故合并的复杂度为O((n+m)logn)。如上图,题目中描述的场景大致如上图所示,假设地平线就是一根数轴,那么在这些数轴的坐标上分布着一些房子和供暖器,这些房子可能包围着一些供暖器,也有可能同一个坐标上同时有房子和供暖器,而这些供暖器也有可能不在房子的范围内。如上图所示,离坐标为3的房子最近的是坐标为0的供暖器,那么对于下一个坐标为5的房子,离它最近的房子就只有可能是坐标为0的供暖器或者在坐标为0的供暖器右端的供暖器,这里很明显就是在在右端的坐标为7的供暖器。解释: 在位置1, 4上有两个供暖器。原创 2023-05-16 09:43:03 · 295 阅读 · 0 评论 -
【刷题之路Ⅱ】LeetCode 86. 分隔链表
我们可以额外创建两个链表Less和Great,将节点值小于x的节点全都按顺序插入到Less中,将节点值大于等于x的节点全都按顺序插入到Great中。所以我们的代码思路很快就可以出来了,我们使用一个cur指针遍历链表中的节点,当cur->val < x时,就将cur尾插到Less链表中,否则就尾插到Great链表中。时间复杂度:O(n),n为链表的长度,我们只需要遍历完链表中的所有节点就可以完成,所以时间复杂度为O(n)。所以我们需要优先记录的信息有两个分别是链表的长度len和尾节点tail。原创 2023-05-08 17:28:09 · 477 阅读 · 0 评论 -
【刷题之路Ⅱ】LeetCode 143. 重排链表
既然链表不支持随机访问而顺序表支持随机访问,那我们就可以想办法先将链表中的节点放到一个节点数组中,然后再按题目给的顺序访问各个节点然后连接成一个新的链表即可。所哟们可以先找到链表的中间节点,然后将中间节点后的链表(不包括中间节点)反转,再让原链表在中间节点处断开,然后再交叉和并这两条链表即可。空间复杂度:O(n),我们需要额外的n个空间来存储指向各个节点的指针。不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。时间复杂度:O(n),n为链表的长度。时间复杂度:O(n),n为链表的长度。原创 2023-05-05 09:46:20 · 1326 阅读 · 1 评论 -
【刷题之路Ⅱ】LeetCode 274&275. H指数Ⅰ&Ⅱ
根据维基百科上 h 指数的定义:h 代表“高引用次数”,一名科研人员的 h指数是指他(她)的 (n 篇论文中)总共有 h 篇论文分别被引用了至少 h 次。当我们创建好了数组统计好了数组counter之后,我们就可以逆序遍历数组counter,先将h初始化为0,然后每遍历到一个元素counter[i]就让好加上counter[i]。因为h不可能大于数组的长度n,所以对于引用次数大于等于n的论文,我们就可以把他算进至少被引用了n次的论文。如果 h 有多种可能的值,h 指数 是其中最大的那个。原创 2023-05-03 10:36:00 · 825 阅读 · 0 评论 -
【刷题之路Ⅱ】LeetCode 61. 旋转链表
而当k等于链表的长度是,其效果就等同于根本没有翻转,所以当k大于或等于链表的长度时候,设链表的长度为len,那么其效果就等同于翻转了k mod len个节点,所以我们就可以先算出链表的长度len,然后执行k %= len,若执行后k等于0,那我们就不用翻转直接返回head即可。所以我们就可以先找到链表的第k个节点和尾节点,然后将这部分链表接到链表的前面即可,但因为是单链表,所以我们实际还要找到的其实是链表的倒数第k + 1个节点(也就是倒数第k个节点的前一个节点)。时间复杂度:O(n),n为链表的长度。原创 2023-05-02 20:49:45 · 758 阅读 · 0 评论 -
【刷题之路Ⅱ】LeetCode 92. 反转链表 II
请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表。其实这一题与"206. 反转链表"的区别就在于,206题是要求我们把整个链表都反转,而这一题只要求我们把链表的一部分反转。方法1的效率其实并不是很高,因为如果left和right刚好是原链表的头和尾时,我们前后一共需要遍历两次链表,分别是找各个节点一次和反转链表一次。注意这里的next的next指向的一定是pre的next,而不是cur,因为cur的位置是一直往后走的,只有指向pre的next才是头插。原创 2023-04-30 18:52:36 · 803 阅读 · 0 评论 -
【刷题之路Ⅱ】LeetCode 24. 两两交换链表中的节点
同时我们还需要一个变量len来记录当前已遍历到的链表的长度,当len为奇数时,我们就将cur尾插到新链表的末尾。当cur后面没有节点或者cur后面只有一个节点时,说明没有可交换的节点了,所以我们迭代停止的条件就是cur->next == NULL 或cur->next->next == NULL。然后我们再让cur向后走到原来Node2的位置,也就是交换后的Node1的位置,即cur = Node1即可完成一轮迭代。给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。原创 2023-04-28 20:12:47 · 834 阅读 · 4 评论 -
【刷题之路Ⅱ】LeetCode 138. 复制带随机指针的链表
首先我们还是需要一个cur指针来遍历原链表中的节点,然后我们需要一个copy指针保存我们待尾插的节点(即cur的next),而为了在尾插完后我们还能找到原链表的下一个节点,我们需要一个next指针来保存我们原链表的下一个节点(即copy的next)。相同的道理,其实我们也可以通过原节点来找到对应的拷贝节点的random所指向的节点,因为我们可以通过原节点来找到原链表中原节点的random指向的节点,那当我们找到了这个节点,这个节点的next不就是对应的拷贝链表中的random指向的节点了吗?原创 2023-04-28 07:37:33 · 419 阅读 · 2 评论 -
【刷题之路Ⅱ】LeetCode 33&81.搜索旋转排序数组Ⅰ&Ⅱ
若nums[mid]!= target,则应判断mid两边的区间[left, mid] 和 [mid, right]主要看有序的那边,这里优先判断左端是否有序。, nums[n-1], nums[0], nums[1], …然后其他地方只需要改变一处,就是在判断左端是否有序时将nums[left] < nums[mid]改成nums[left]原创 2023-04-19 11:37:11 · 378 阅读 · 0 评论 -
【刷题之路Ⅱ】牛客 NC107 寻找峰值
其他情况判断是否有nums[i] > nums[i - 1] && nums[i] > nums[i + 1],如果成立,则返回i。则mid可能是峰值,此时应该执行right = mid(不能跳过mid,因为mid可能是峰值),使区间向峰值靠近。当i等于numsLen - 1时,判断nums[i]是否大于nums[i - 1],若大于,则返回i;当i等于0时,判断nums[i]是否大于nums[i + 1],若大于,则返回i;时间复杂度:O(n),n为数组元素个数,我们只需要遍历一遍数组即可。原创 2023-03-22 16:58:18 · 434 阅读 · 0 评论 -
【刷题之路Ⅱ】将你的二分法修炼到极致!LeetCode 34. 在排序数组中查找元素的第一个和最后一个位置
而且,当我们找target第一次出现的下标之后,就可以确定target最后一次出现的下标的范围一定是在第一次出现的下标之后的后半部分,所以我们在找target最后一次出现的下标的时候就可以缩小范围了。题目要求我们使用时间复杂度为O(logn)的算法,已经在暗示我们要使用二分查找法了,我们可以先分别找出出现第一次的target的下标和出现最后一次的target的下标,然后将它们写进数组,返回即可。以保证范围能够向右边逼近。确实,NC105要求的是第一次出现的下标,而我们这一题要求的是第一次最后一次的下标。原创 2023-03-20 16:23:08 · 238 阅读 · 0 评论 -
【刷题之路Ⅱ】LeetCode 11.盛水最多的容器
所以我们每一次枚举都要找到较短的那一条short_plank,用short_plank乘上两条垂线之间的距离就得出这两条垂线所形成的容器的容量了。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i])。解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。时间复杂度:O(n),其中n为数组元素个数,我们只需要遍历一遍数组及可。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。当我们枚举完所有的组合,我们也就求出了最大的盛水量。原创 2023-03-18 13:10:17 · 451 阅读 · 0 评论 -
【刷题之路Ⅱ】LeetCode 5.最长回文子串
而且当j - i < 3时,也就是子串的长度小于等于3(子串的实际长度为j - i + 1),我们就并不需要,判断p[i + 1][j - 1]了,只需要判断s[i]和s[j]是否相等即可,因为在是s[i]和是s[j]中间就只有可能剩一个或者零个字符了。其实回文串是具有动态转移性质的,也就是说一个回文串去掉两端的字符后,剩下的串依旧是一个回文串,所以我们在获得一个子串后,可以先看它两端的字符是否相等,如果不相等,就不是一个回文子串,如果相等就接着看去掉两段字符后的字符串是否为回文串。原创 2023-03-14 10:18:38 · 479 阅读 · 1 评论 -
【刷题之路Ⅱ】牛客 BM18 二维数组中的查找
3、如果target < flag,说明target在更小的地方,而flag下边的元素又都是大于flag的,间接大于target,说明flag所在的列是无效的,2、如果target > flag,说明target在更大的位置,而flag左边的元素显然都是小于flag的,简介就小于target,说明第0行是无效的,而竖着层数的增加,每一列上的元素也是递增的,因此我们就可以先找到target所在的层数,然后再遍历这一层,若找到target,则直接返回true。每一列都按照从上到下递增的顺序排序。原创 2023-03-12 15:34:57 · 107 阅读 · 0 评论 -
【刷题之路Ⅱ】牛客 NC105 二分查找-II
其实只需要判断左边界left是否等于target即可,因为左边界的改动的条件一定是上一轮nums[mid] < target,说明target在mid后面,而左边界改动进行的操作又是left = mid + 1,那如果下次的nums[left] == target,不就恰好说明找到了第一次出现的target了吗?故当left与right重合时,就可以判断lef指向的元素是否等于target,如果等于,则说明此时left指向的元素就是第一次出现的target,若不等于,则说明数组中不存在target。原创 2023-03-10 16:42:10 · 194 阅读 · 0 评论 -
【中篇启航!】牛客剑指offer JZ56 数组中只出现一次的两个数字
由于题目中给出的元素最大为1000000,所以我们可以先创建一个长度为1000001的数组fre,然后对数组array进行遍历,每遍历到一个元素就执行fre[array[i]]++,记录array数组中每个元素出现的频数,然后再次遍历一遍数组array,当fre[array[i]] == 1时,将array[i]写入一个数组(我们可以直接将这两个数写到array[0]和array[1]。如果要我们分辨一个数是奇数还是偶数,熟悉二进制的我们肯定能想到,奇数的二进制序列的最低位肯定是1,而偶数的肯定是0。原创 2023-03-08 10:24:06 · 135 阅读 · 0 评论