自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 剑指Offer题目笔记33(并查集)

​ 一个班级可以包含一个或多个朋友圈,对应的图中可能包含一个或多个子图,每个朋友圈对应一个子图。图的搜索算法可以用来计算图中子图的数目。​ 把输入数组中的每个字符串看成图中的一个节点。如果两个字符串相似,那么它们对应的节点之间有一条边相连,也就属于同一个子图。例如,字符串[“tars”,“rats”,“arts”,“star”]根据相似性分别属于两个子图。如果将每个整数看成图中的一个节点,相邻的(数值大小相差1)两个整数有一条边相连,那么这些整数将形成若干子图,每个连续数值序列对应一个子图。

2024-04-18 22:05:55 326

原创 剑指Offer题目笔记32(拓扑排序)

【代码】剑指Offer题目笔记32(拓扑排序)

2024-04-18 12:21:42 744

原创 剑指Offer题目笔记31(图的搜索)

从节点0出发开始搜索。被除数和除数都对应图中的节点,商是两个变量的除法的结果,表达的是变量之间的关系,因此商应该是边的属性。​ 二分图的节点可以分成两种不同的类型,任意一条边的两个节点分别属于两种不同的类型。​ 逐一扫描矩阵的每一个格子,如果遇到一个值为1的格子并且它不在已知的岛屿上,那么就到达了一个新的岛屿,于是搜索这个岛屿并且计算它的面积,在比较所有岛屿的面积之后就可以知道最大的岛屿的面积。表示单词演变的图也是一个无权图,按照题目的要求,图中两个节点的距离是连通两个节点的路径经过的节点的数目。

2024-04-16 18:38:57 713

原创 剑指Offer题目笔记30(动态规划背包问题)

​ 在计算f(i,j)的值时需要用到f(i-1,j)、f(i-1,j-nums[i-1])、因为f(i-1,j-nums[i-1])保存在f(i,j)之前,那么如果从左到右计算,那么会将f(i-1,j-nums[i-1])覆盖为f(i,j-nums[i-1]),所以只能从右到左计算。​ 给定一个非空的正整数数组nums和一个目标值t,数组中的所有数组都是唯一的,请计算数字之和等于t的所有排列的数目。​ 给定正整数数组coins表示硬币的面额和一个目标总额t,请计算凑出总额t至少需要的硬币数目。

2024-04-09 12:00:00 943

原创 剑指Offer题目笔记29(动态规划矩阵路径问题)

​ 在计算f(i,j)时需要用到f(i-1,j)和f(i,j-1)的值。接下来在计算f(i,j+1)时需要用到f(i-1,j+1)和f(i,j)的值。由于在用f(i-1,j)计算出f(i,j)之后就不再需要f(i-1,j),因此可以只用一个位置来保存f(i-1,j)和f(i,j)的值。值得注意的是,f(i-1,j)在完成f(i,j)的计算之后再也用不到了,因此将f(i-1,j)和f(i,j)保存到同一个数组dp的同一个位置“dp[j]”中。而f(i,j-1)在计算f(i,j)之前就已经计算好了。

2024-04-08 12:00:00 955

原创 剑指Offer题目笔记28(动态规划双序列问题)

​ 观察上述代码,可以发现f(i,j)依赖于f(i-1,j)、f(i,j-1),f(i-1,j)的值在计算出f(i,j)之后就不再需要,因此可以用同一个位置保存f(i-1,j)和f(i,j)的值。​ 观察上述代码,我们可以发现f(i,j)的值依赖于f(i-1,j-1)或f(i-1,j)、f(i,j-1),我们将 f(i-1,j)都保存在数组dp下标j+1的位置,f(i,j-1)就是f(j-1),f(i-1,j-1)用临时变量prev保存,将二维数组压缩为一维数组。

2024-04-07 12:00:00 872

原创 剑指Offer题目笔记27(动态规划单序列问题)

​ 由于小偷到达标记为i的房屋是有两个选择,他进去偷东西和不进去偷东西,定义f(i)为不进去偷东西,g(i)为进去偷东西,因此f(i)= max(f(i-1),g(i-1)),g(i) = f(i-1) + nums[1]。​ 由下到上,先求出f(0)和f(1)的值,再通过状态转移方程f(i) = Math,max(f(i-1),f(i-2) + nums[i])求出f(2)以此类推求得f(i)。​ 输入一个没有重复数字的单调递增的数组,数组中至少有3个数字,请问数组中最长的斐波那契数列的长度是多少。

2024-04-06 13:21:43 1214

原创 剑指Offer题目笔记26(动态规划的基础知识)

例如求f(9)就需要先求f(8)和f(7),而计算f(8)就需要计算f(7)和f(6),以此类推,需要重复计算的数据量太大、时间复杂度很高。求解f(i)时只需要f(i-1)和f(i-2)的结果,从f(0)到f(i-3)的结果其实对求解f(i)并没有任何作用。也就是说,在求每个f(i)的时候,需要保存之前的f(i-1)和f(i-2)的结果,因此只要一个长度为2的数组即可。​ 自下而上地解决这个过程,也就是从子问题入手,根据两个子问题f(i-1)和f(i-2)的解求出f(i)的结果。

2024-04-06 13:17:56 316

原创 剑指Offer题目笔记25(使用回溯法解决其他类型问题)

当处理到字符串中的某个字符时,如果包括该字符在内后面还有n个字符,那么此时面临n个选项,即分割出长度为1的子字符串(只包含该字符)、分割出长度为2子字符串(即包含该字符及它后面的一个字符),以此类推,分割出长度为n的子字符串(即包含该字符在内的后面的所有字符)。因为要生成n个左括号和n个右括号,故需要走2n步,每一步生成一个括号,每一步都面临两个选项,既可能生成左括号也可能生成右括号。​ 输入一个正整数n,输出所有包含n个左括号和n个右括号的组合,要求每个组合的左括号和右括号匹配。

2024-04-03 12:54:57 608

原创 剑指Offer题目笔记24(集合的组合、排序)

每一步从集合中取出下标为i的数字,此时面临两个选择,一个选择是跳过该数字,不将该数字添加到组合中,另一个选择就是将数字添加到组合中,由于一个数字可以在组合中重复出现,所以下一步仍然处理下标为i的数字,如果集合中包含n个元素,那么生成子集可以分为n步,每一步从集合中取出一个数字,此时面临两个选择,将该数字添加到子集中或不将该数字添加到子集中。如果组合只能有k个元素,那么生成组合可以分为k步,每一步从集合中取出一个数字,此时面临两个选择,将该数字添加到组合中或不将该数字添加到组合中。

2024-04-02 19:51:34 552

原创 剑指Offer题目笔记23(归并排序)

先扫描链表数组将所有排序链表的头节点添加到最小堆,然后将最小堆堆顶的链表节点弹出,因为最小堆堆顶的链表节点是整个堆中链表节点值最小的,弹出后再判断堆顶的链表节点是否存在下一个节点,如果存在就添加到最小堆,如果不存在就不需要添加,以此循环,直到堆中不存在元素。​ 输入的k个排序链表可以分为两部分,前k/2个链表和后k/2个链表。如果将前k/2个链表和后k/2个链表分别再分为两个排序链表,再将两个排序链表合并,那么所有链表都合并了。将链表分为两个子链表,在对两个子链表排序后再将它们合并为一个排序的链表。

2024-03-30 17:14:05 600

原创 剑指Offer题目笔记22(快速排序)

​ 快速排序的基本思想是分治法,排序过程如下:在输入数组中随机选取一个元素作为中间值(pivot),然后对数组进行分区(partition),使所有比中间值小的数据移到数组的左边,所有比中间值大的数据移到数组的右边。接下来对中间值左右两侧的子数组用相同的步骤排序,直到子数组中只有一个数字为止。

2024-03-29 19:11:31 440

原创 剑指Offer题目笔记21(计数排序)

先统计arr1中的每个整数在数组中出现的次数记为counts,然后按照arr2的顺序将每个整数按照它出现的次数填入到数组中,扫描完arr2数组后,继续扫描counts数组,如果counts数组中出现整数出现次数不为0时,将每个整数按照它出现的次数填入到arr2数组中。​ 输入两个数组arr1和arr2,将数组arr1中的数字按照数组arr2中的数字的相对顺序排序。如果数组arr1中的数字在arr2中没有出现,那么将这些数字按递归的顺序排在后面。​ 输入一个区间的集合,将重叠的区间合并。

2024-03-29 14:52:38 620

原创 剑指Offer题目笔记20(在数组范围内二分查找)

​ 门卫走开H小时,有n堆香蕉,狒狒去吃香蕉,狒狒一个小时只能吃一堆香蕉,狒狒要在门卫回来前将香蕉吃完,问狒狒每个小时至少得吃多少根香蕉。​ 输入一个非负整数,计算它的平方根。

2024-03-28 17:37:05 450 1

原创 剑指Offer题目笔记19(二分查找)

生成一个随机数p,先选取位于数组中间下标的值,如果p小于当前值,再判断p与前一位的值的大小,如果前一位的值小于等于p,那么返回当前下标,如果p大于当前值,那么权重值在数组前半部分,如果p大于当前值,那么权重值在数组后半部分。因为该数组是先递增后递减就像一座山峰,我们要求峰顶的下标,因此需要找到比它左右两边数字都大的数字对应的下标,如果这个数字比它左边的数字大,并且比它右边的数字要小,故峰顶在后半部分,如果这个数字比它左边的数字小,并且比它右边的数字要大,故峰顶在前半部分。

2024-03-27 23:16:09 514

原创 剑指Offer题目笔记18(前缀树的应用)

​ 使用前缀树,将每个整数转换为二进制,并将整数的每个数位保存下来,最后从高位开始扫描整数num的每个数位。如果前缀树中存在某个整数的相同位置的数位与num的数位相反,则优先选择这个相反的数位,这是因为两个相反的数位异或的结果为1,比两个相同的数位异或的结果大。​ 给定一个由词根组成的字典和一个英语句子,将英语句子中的单词在字典中有它的词根,则用词根替换该单词,然后输出替换后的句子。​ 给定一个单词数组,将它们编码成一个字符串和n个下标,用‘#’字符将单词隔开,然后单词a是单词b的后缀则不需要隔开。

2024-03-26 20:07:06 1763

原创 剑指Offer题目笔记17(堆的应用)

​ 先从第一个数组中选取前k个数字与第二个数组的第1个数字组成数对放入最小堆中,然后将堆顶的数对弹出,添加到链表中,然后向后移动第二数组的数字并与第一个数组中取第1个数字组成数对放入最小堆中,直到链表的长度达到k或者堆中为空。​ 给定两个递增排序的整数数组,从两个数组中各取一个数字u和v组成一个数对(u,v),找出和最小的k个数对。​ 找出数组中出现频率’最高的k个数字。

2024-03-25 12:00:00 403 1

原创 剑指Offer题目笔记16(TreeSet和TreeMap的应用)

​ 使用TreeSet作为数据容器,因为需要从一个大小为k的数据容器中找出小于或等于某个数字的最大值及大于或等于某个数字的最小值,逐一扫描数组中的每个数字,对于每个nums[i]来说,应该先从它前面k个数字中找出小于或者等于nums[i]的最大的数字,如果该数字与nums[i]的差的绝对值不大于t,则返回true,反之返回false。否则,先从它前面k个数字中找出大于或者等于nums[i]的最小的数字,如果该数字与nums[i]的差的绝对值不大于t,则返回true,反之返回false。

2024-03-24 17:00:00 318 1

原创 剑指Offer题目笔记15(二叉搜索树)

​ 从根节点开始,每个节点都与节点p对比,如果当前节点的值小于节点p,那么节点p的下一个节点就位于当前节点的右子树中,如果当前节点的值大于节点p,那么节点p的下一个节点就可能是当前节点或者位于当前节点的左子树中,就先将当前节点记录下来,然后前往当前节点的左子树,确定是否存在大于节点p,但是小于当前节点的值。​ 使用中序遍历,因为二叉搜索树是左节点的值小于等于根节点,根节点小于等于右节点的值,所以要是向使用每个节点都没有左子树,那么就需要先遍历左节点。​ 实现二叉搜索树的迭代器,补全3个函数。

2024-03-23 14:48:15 914

原创 剑指Offer题目笔记14(二叉树的深度优先搜索)

由于要找出节点值之和为7的路径,而12与5的差值是7,这就说明从节点5的下一个节点(即节点2)开始到节点6结束的路径经过的节点值之和为7。​ 使用后序遍历,因为当路径到达某个节点时,该路径可以前往它的父节点,也可以前往它的左节点,还可以前往它的右节点,但是一旦路径同时经过它的左右节点时,则不能前往它的父节点。​ 使用前序遍历,每当遍历到一个节点时,都计算从根节点到当前节点的路径表示的数字,如果当前节点还有子节点的话,就将数字接着传下去,如果没有子节点的话,则将数字累加起来。

2024-03-21 20:45:17 420 1

原创 剑指Offer题目笔记13(二叉树的广度优先搜索)

先将头节点存入队列,然后从上到下按层从左到右扫描,找出第一个左节点或右节点存在空缺的节点,如果它缺少左节点,那么新节点就是它的左节点,如果它缺少右节点,那么新节点就是它的右节点,如果它的左右节点都不在空缺,那么就将该节点移除队列,将它的左右节点存入队列。​ 使用队列作为数据容器,创建两个队列queue1、queue2,queue1只放入当前扫描层的节点,而queue2只放入当前扫描的下一层的节点。​ 将不同层的节点放入不同的队列中。​ 使用队列作为数据容器。​ 站在二叉树的右边,返回从上到下看到的节点。

2024-03-20 20:23:37 263 1

原创 剑指Offer题目笔记12(队列的应用)

​ 使用队列作为数据容器,与上一题类似,根据题目描述,可以将某个时间范围的所有时间看成窗口,当某个时间由于过早超出时间范围,就需要删除最早的时间,这是一种”先进先出“的顺序,由此采用队列作为数据容器。​ 使用队列作为数据容器,因为根据题目描述,可以在窗口中添加数字,当窗口中数字的数目超出限制,就需要删除最早进入窗口的数字,这是一种”先进先出“的顺序,由此采用队列作为数据容器。​ 每次调用成员函数next时都会在滑动窗口中添加一个整数,并返回滑动窗口中的所有数字的平均值。

2024-03-19 20:52:52 157 1

原创 剑指Offer题目笔记11(栈的应用)

​ 使用栈实现数据容器,让栈保留对应温度的下标,每次从数组中读取一个温度w1,然后将其与位于栈顶下标所对应数组中的温度w2进行比较,当w1>w2时,就找到更高的温度了,就将栈顶元素进行出栈,然后接着跟下一个栈顶下标所对应数组中的温度w3进行对比,如此反复直到栈顶下标所对应数组中的温度比较大或者栈内为空,则将温度w1对应的下标进行入栈。​ 输入一个表示小行星的数组,正整数向右运动,负整数向左运动,如果两颗小行星相撞,体积小的小行星直接消失,大的小行星不受影响,相同体积则一起消失,求最终剩下的小行星。

2024-03-18 23:23:17 378

原创 剑指Offer题目笔记10(哈希表的应用)

注意:如果字符 "app"和 "apple"匹配时,第二个字符串相对短一些,然后根据词典编纂规则 “apple” > “app”,因为 ‘l’ > ‘∅’,其中 ‘∅’ 是空白字符,定义为比任何其他字符都小。​ 使用数组模拟哈希表,遍历字符串s,将数组对应的位置进行增加,再遍历字符串t,将数组对应的位置进行减少,最后遍历数组,当数组中所有元素都为0时,返回true,反之返回false。​ 使用哈希表进行存储,键为一个单词,值为这个单词所对应的变位词所组成的链表。​ 将一组单词按照变位词进行分组。

2024-03-17 14:14:33 408 4

原创 剑指Offer题目笔记9(哈希表的设计)

​ 设计一个数据结构,使插入、删除和随机访问的时间复杂度是O(1)。

2024-03-16 14:21:09 359 1

原创 剑指Offer题目笔记8(双向链表和循环链表)

​ 使用递归函数展平链表,每次进入递归之前先保留当前节点的下一节点,递归结束后将节点的子链表设置为null,当前节点的后节点设置为子链表的头节点,子链表的头节点的前节点设置为当前节点,子链表的尾节点的后节点设置为当前节点的下一节点,当前节点的下一节点的前节点设置为子链表的尾节点的后节点。​ 在该循环链表中插入节点,保证插入节点之后的循环链表仍然是排序的。​ 将多级双向链表展平成普通的双向链表。

2024-03-15 21:37:25 489 1

原创 剑指Offer题目笔记7(反转链表)

​ 重排链表时节点的顺序变成L0->Ln->L1->Ln-1->…,需要我们先切割链表,然后将后半段进行反转,然后再按前半段一个节点、后半段一个节点进行链接。​ 使用3个指针,第一个指针保存当前节点的前一个节点,第二个指针保存当前节点,第三个指针保存当前节点的后一个节点。​ 先对两条链表进行反转,再从头开始遍历两条链表并进行相加。​ 反转该链表并输出反转后链表的头节点。​ 判断一个链表是不是回文。

2024-03-14 20:36:04 352

原创 剑指Offer题目笔记6(双指针)

​ 首先分别找出两条链表的长度countA、countB,使用前后指针,让前指针位于比较长的链表头节点、后指针位于比较短的链表头节点,如果A链表比较长,就让前指针在A链表上向前移动countA-countB位,然后前后指针以相同的速度向前移动,直到找到第一个相同的节点。​ 使用前后双指针,前指针先提前移动朝着指向下一个节点的指针移动n-1步,然后后指针指向链表的头节点,再让两个指针一起移动,当前指针到达链表尾节点时第二个指针刚好指向倒数第k个节点。​ 找出两个部分重合链表的第一个重合节点。

2024-03-13 21:32:14 354

原创 剑指Offer题目笔记5(回文字符串)

​ 使用双指针,左指针从前到后,右指针从后到前,对字符串进行遍历,当左指针与右指针重叠时,停止。并且对每一次指针的值进行两次判断。​ 求字符串中有多少回文连续字符串。

2024-03-12 21:21:36 336 1

原创 剑指Offer题目笔记4(双指针)

​ 判断字符串s2中是否包含字符串s1的某个变位词(变位词就是指组成各个单词的字母以及每个字母出现的次数完全相同,只是字母排列的顺序不同),例如post、stop、tops等。​ 找出字符串s中包含字符串t的所有字符的最短子字符串。​ 找出字符串s2的所有变位词在字符串s1的起始下标。​ 求不含重复字符的最长子字符串。

2024-03-11 13:29:53 795 1

原创 剑指Offer题目笔记3(累加数组数字求子数)

首先把数组中所有0替换为-1,那么题目就变成求-1和1的个数相同的最长连续子数组的长度,又因为如果-1和1的个数相同,那么这个题目就变成求数字之和为0的最长子数组长度。​ 先遍历一遍数组,计算出数组数字的总和mation,再进行遍历下标,使用sum对经过下标的数字进行累加,当sum == mation - sum - nums[i]时,返回下标i。​ 和第十题解法类似,但是这题的map的键为从第一个数字开始累加到当前扫描到的数字之和、值为当前扫描的数字的下标。​ 求出左上角坐标到右下标的子矩阵。

2024-03-10 15:19:15 379 1

原创 剑指Offer题目笔记2(双指针)

​ 设输入数组为nums,使用双指针,创建左指针left、右指针right、连续子数组之和为sum,左右指针同时从下标0开始,当sum>=k时,left++;记录每一次sum>=k时连续子数组的长度,直到left > nums.length或right > nums.length。​ 与上一道题类似,设输入数组为nums,使用双指针,创建左指针left、右指针right、连续子数组乘积为product,左右指针同时从下标0开始,循环right,当product>=k时,left++;

2024-03-09 22:25:48 482 1

原创 剑指Offer题目笔记1(二进制)

这个题目限制我们不能使用乘号和除号、求余号进行运算。所以我们选择用减法实现除法。但是当被除数太大并且除数太小会导致执行次数太多,效率太低。我们需要优化该解法,当被除数大于除数时,继续比较被除数是否大于除数的2倍,如果是,重复该操作,就可以将时间复杂化度提升到O(logn)。上述讨论被除数和除数都是正整数,当有负数时则可以将它们先转正数再进行计算,将负数转为正数之前我们知道int类型的取值范围在(-231-1),所以直接将负数转为正数可能出溢出。

2024-03-08 22:01:36 871 2

空空如也

空空如也

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

TA关注的人

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