
优选算法
文章平均质量分 82
优选算法
写不来CODE
我很懒,还没有个人简介
展开
-
二叉树——队列bfs专题
我们之前遇到过二叉树的层序遍历,只需要用队列先进先出的特性就可以达到层序遍历的目的。而这里不是二叉树,也就是说让节点的孩子入队列时不仅仅是左右孩子了,而是它的所有孩子。而我们看这棵多叉树的构造,它的孩子是存储在数组中的。所以我们在让孩子入队时只需要依次让数组中的所有节点入队列即可。而这道题的要求是返回一个二维数组,数组的元素就是每一层的层序遍历结果。原创 2025-04-06 22:04:42 · 547 阅读 · 0 评论 -
栈(LIFO)算法题
注意,我们需要重复处理,而不是处理一次相邻的相同元素就结束了。对示例来说,如果只进行一次处理,结果为aaca,但是处理之后又出现了相邻的重复元素,我们还得继续处理,最后结果就是ca。解法:借助栈来模拟我们可以将字符串中的元素依次入栈,元素入栈前判断是否与栈顶元素相等,如果相等就弹出栈顶元素,继续判断下一个元素。等到字符串全部入栈,栈中的就是最终答案。但是我们没有必要弄一个stack出来,因为这样最终结果是逆序的,我们可以采用string来模拟栈的行为。原创 2025-03-16 22:08:23 · 697 阅读 · 0 评论 -
字符串算法题
题目要求找出所有字符串的公共前缀,如果没有公共的前缀就返回空字符串。我们以第一个字符串为标准,依次比较所有字符串的每一位,如果都相同,则比较下一个位置,如果不同,那么前一个位置就是最长的公共前缀。在纵向比较的时候要避免越界,因为第一个字符串的长度有可能比后面的字符串长,所以除了字符不相等外,i越界,也是一个判断条件。两个两个字符串进行比较,用它们得出的前缀和与第三个字符串继续比较。重复该过程。如果在某一个比较过程中发现前缀和的长度变为0,那就说明所有字符串没有公共的前缀和。原创 2025-03-16 20:57:40 · 885 阅读 · 0 评论 -
哈希表算法题
因为数组是无序的,所以我们无法直接使用双指针。找两个数之和为target,我们可以固定一个数x,然后在其前面找有没有一个数等于target-x。如果没有,我们x就走到下一个位置。然后重复找前面有没有一个数等于target-x的过程。这个算法是否正确呢?答案是肯定的。因为如果我们从后往前看的话,就知道,其实就相当于是个反向的暴力。我们在反向遍历的过程中,一直在找该数的前面有没有target-x的这个数出现过。原创 2025-03-15 12:34:40 · 551 阅读 · 0 评论 -
链表算法题目
cur2指向头节点,cur1指向空,然后用cur2遍历原链表,遍历的同时,让cur2的next指向cur1,实现逆置,然后让cur1走到cur2的位置,然后cur2走到下一个位置。所以我们也要保证进位不为0。返回的过程中,将该层的head的next的next指针指向自己即head的前一个节点的next指针指向自己,此时就达到了后一个指向前一个,接着将head的next指针指向空,避免成环。简单来说,对于原链表来说,每两个一组的节点,第一个节点是新链表的第二个节点,第二个节点是新链表的头节点。原创 2025-03-08 21:20:39 · 931 阅读 · 0 评论 -
分治——归并排序算法题
在合并阶段,我们无法在原数组进行合并,需要借助一个。原创 2025-02-25 21:38:30 · 728 阅读 · 0 评论 -
分治——快速排序算法题
分治解决问题的思想就是大事化小,将一个大问题分解成若干个子问题。这道题其实就是让我们对数组进行操作,使操作之后的数组呈现出三段区间[0,left],[left+1,right-1],[right,size-1],这三个区间的元素分别都是0,1,2.既然是进行数组分块,我们就可以使用双指针的思想来解决:首先定义一个指针i;然后在分别创建两个指针和我们的目的是将数组分为三块,。原创 2025-02-24 17:08:48 · 946 阅读 · 0 评论 -
模拟算法题
模拟算法题我们只需要按照题目的意思一步一步走,将这些步骤转换成代码即可题目要求将字符串中所有的问号都改为其他字母,但是要求不能与左右两边的字母重复,返回一种结果即可。遍历原字符串,当遍历到问号时,我们遍历26个英文字母,找到既不与前面相同也不与后面相同的字母,修改该位置,继续遍历。在遍历的过程中需要注意首元素以及尾元素,它们只需要判断相邻的一个元素即可,要避免越界访问。原创 2025-02-06 18:12:20 · 704 阅读 · 0 评论 -
位运算算法题
法一:我们直接借助一个字符数组来模拟哈希表统计字符串即可,并且我们没有必要先将所有字符都放入字符数组中,边插入边判断,当我们要插入某个字符的时候,发现其已经出现了,此时必然重复,直接返回false。法二:因为字符串只包含26个小写字母。我们可以用一个int变量的26个bit位来依次表示26个小写字母。0表示没出现,1表示出现,如果遍历到那个字符,发现其对应的二进制位为1,表示该字符重复出现,返回false。我们首先定义一个int变量mark来记录字符的出现次数。原创 2025-02-02 17:40:50 · 978 阅读 · 0 评论 -
基础位运算
左移操作符,使二进制向左边移动指定位数,同时在其右侧补0左移操作符可以用来提高乘法的效率:2*n -> 1<<n,x*2*n -> x << n。原创 2025-01-30 21:08:34 · 742 阅读 · 0 评论 -
前缀和——矩阵区域和
我们这里的mat数组是从0,0位置开始的。而我们在预处理dp数组时,为了避免边界情况(计算后的下标小于0),下标是从1,1开始的。所以我们在预处理时加最后的d时,其实对应的是mat数组的mat[i-1][j-1]还有就是使用dp数组时,answer返回数组的下标是从0,0开始的,而dp数组从1,1开始才是有效数据。就如示例一种answer的(0,0)位置的值,它的左上下标已经越界了,所以我们要对其进行处理。题目所求的矩阵, 本质就是需要求一段矩阵的和,所以快速求矩阵的和我们就可以使用二维前缀和来解决问题。原创 2025-01-26 16:39:55 · 985 阅读 · 0 评论 -
前缀和——连续数组
因为最终结果ret = i - dp[sum].说明此时(0,i)这个区间满足要求,长度是i+1.而直接用公式i-mp[sum] = i.为了满足结果,所以dp[0] = -1.但是我们在遍历的过程中,可能有很多相等的sum,它们对应的下标不同,但是如果哈希表中已经有了sum,就没必要再插入了,因为后面插入的sum对应的下标更大,最终的结果就更小。我们可以对数组进行转换,让我们找0,1相等的数组,我们可以将0变为-1,此时问题就转变为求和为0的最长的子数组。经过转换,这道题就类似于求和为k的子数组了。原创 2025-01-24 17:01:33 · 317 阅读 · 0 评论 -
前缀和——和可被k整除的子数组
所以我们的问题就转化为了,当遍历到i位置的时候,其实sum%k就已知了,我们只需要在(0,i-1)这个区间里面,找有多少个前缀和的余数 == sum%k的即可。还有就是有可能导致漏答案:[-1,2,7] k = 2,当遍历到2时,此时-1%2 = -1,如果不进行修正,2这个答案就漏掉了,但是我们对余数进行修正—— (-1+2)%2 = 1,与当前位置的前缀和1的余数相等。第三点就是C++负数对正数取模,它的结果是一个负数,我们需要对其进行修正,所以我们让其加上一个k,sum%k +k。原创 2025-01-24 17:00:57 · 280 阅读 · 0 评论 -
前缀和——和为k的子数组
当right走到了结尾之后,此时left++,right又要回到left的位置重新遍历,所以left和right并不是向同一方向移动,所以不能使用滑动窗口解决问题。我们将数组分为两部分,一部分是以i为结尾的子区间,另一部分是x区间,而这两个区间之和就是dp[i],所以满足k+x = dp[i]。所以如果以i为结尾的子数组和为k的话,则x子数组一定满足dp[i]-k。所以我们需要借助一个哈希表,将前缀和存在里面,我们只需要在里面找到有几个和为dp[i]-k的即可。找一段连续的子区间,该子区间的和为k。原创 2025-01-23 15:35:30 · 420 阅读 · 0 评论 -
前缀和——除自身以外数组的乘积
但是我们需要对数组f,g 数组进行特殊处理,当i分别为0和n-1时,f,g数组会分别越界,所以我们可以对这两个位置进行特殊处理:f[0]表示(0,-1)这个区间的积,该区间不存在,所以我们可以将其置为1。我们要计算某个位置左右区间所有元素的积,那么我们就可以分别记录下左右区间的积,最后将两个值相乘即可。同样,我们借助来个数组来存储f,g。f[i]表示(0,i-1)这段区间的积,g[i]表示(i+1,n-1)这段区间的和。时间复杂度:处理前后缀积数组需要遍历两边数组,最后遍历下标也需要遍历一边数组,综上,原创 2025-01-21 20:52:36 · 441 阅读 · 0 评论 -
前缀和——寻找数组的中心下标
时间复杂度为O(n)原创 2025-01-20 17:51:07 · 631 阅读 · 0 评论 -
前缀和——模板 二维前缀和
A区域就是dp[i-1][j-1],D区域其实就是arr[i][j],现在剩下的就是C和B了。这里的dp[i][j]表示的是从(1,1)~(i,j)这个区间的和。输入一个m行n列的矩阵,然后进行q次操作,每次操作输入4个数,作为两个点的坐标,计算这两个点为对角线的矩阵的和。因为我们这里的下标是从1开始的,所以我们在申请空间的时候,行和列都得多申请一行/列。时间复杂度:处理dp数组时,我们需要遍历一遍数组m*n,接着我们进行q次操作,但是每次操作的时间复杂度都是O(1),所以综上,暴力解法那我们就遍历贝。原创 2025-01-19 14:18:07 · 808 阅读 · 0 评论 -
前缀和——【模板】前缀和
题目还是很好理解的,先分别输入两个数,一个是数组的长度,一个是操作的次数。我们接着下面的图来分析,要求2~4这个区间的和,其实就是红色线对应区间的值减去绿色线对应的区间的值。题目已经给了我们区间的起始位置和结束位置,我们只需要遍历一遍数组,从子区间的起始位置开始计算,直到子区间的结束位置即可。我们该题下标从1开始,我们开数组的时候开n+1个空间,第一个空间的值赋为0即可,不会影响dp数组和最后的结果。当我们有了前缀和数组,让我们求l~r这个区间的和,其实就是前缀和数组dp[r] - dp[l-1]的结果。原创 2025-01-18 12:10:59 · 812 阅读 · 0 评论 -
二分查找算法——点名
此时下标i就是结果。一共有0~n-1这n个数,数组有n-2个数,数组的下标与学号是统一的,说明0~n-2个数都在数组中,那么缺少的数就是n-1。但是我们需要注意边界情况:如果数组的下标和元素都是一一对应的,那么此时left和right会在数组的结束位置,但此时的下标并不是结果,下标+1才是结果。我们观察上图可以发现,在根据二段性分成的两个区间中,右区间的左端点的下标就是缺失的数,所以我们要寻找右区间的左端点。我们先将0~n-1这n个数的和求出来,然后减去数组的和,剩下的就是丢失的数。原创 2025-01-15 21:11:22 · 750 阅读 · 0 评论 -
二分查找算法——寻找旋转排序数组中的最小值
因为数组原本是升序的,每一次旋转都是将最大值转到了前面,所以我们的数组应该是先上升,然后突然降到最小值,然后持续上升。数组本来是升序的,我们要在旋转后的数组中,返回最小值。题目上面要求我们使用logn的算法解决,所以这道题肯定是二分没跑了。寻找数组的最小值,我们管它旋转没旋转,旋转几次,我们直接遍历一个数组,同时更新最小值即可。时间复杂度:我们使用了二分算法,每一次都丢弃了一半内容,所以。时间复杂度:我们需要完整的遍历一边数组才能拿到最小值,所以。空间复杂度:我们在该过程中,只只用了有限个变量,所以。原创 2025-01-14 20:48:26 · 273 阅读 · 0 评论 -
二分查找算法——寻找峰值
我们看上图,之所以说一定有结果是因为即使高的那边一直递减,那么他也是大于左右两边的,满足峰值要求。另一边有可能有结果是因为,那一边有可能一直递减,也有可能出现递增,所以判断这一边意义不大,直接舍弃即可。圆圈的位置都是峰值。图一和图二,它们之所以是峰值,是因为峰值的要求是大于左右两边的元素,而他们的另一边是无限趋于负无穷大的,所以边缘位置也是大于左右两边的,所以属于峰值。既然峰值元素要求大于左右两边的元素,那么暴力解法就是遍历整个数组,找到一个元素,该元素满足既大于左边又大于右边,返回该位置即可。原创 2025-01-13 23:12:59 · 379 阅读 · 0 评论 -
二分查找算法——山脉数组的峰顶索引
因为题目明确说明,arr一定是一个山脉数组。在上升阶段包含峰值,都满足当前位置大于前一个位置,在下降阶段,都满足当前位置小于前一个。当mid落到有区间,该位置的值不可能是结果,所以我们直接让right跳过mid,所以right = mid-1.当mid落到左区间,该位置的值有可能就是峰值,所以我们不能让left跳过mid,所以left = mid;因为我们这里并没有单独处理等于的情况,所以这里不能用简单二分,而得用查找区间右端点的写法。因为题目明确告诉我们这是一个山脉数组,所以它的二段性还是非常明显的。原创 2025-01-13 22:22:32 · 275 阅读 · 0 评论 -
二分查找算法——搜索插入位置
我们可以对数组进行分析,target会将数组分为两个部分,[0~target]<=target,[target+1,size-1]>target。查找完成后,会剩余一个元素,该元素要么是target,要么不是。如果不存在,我们就在遍历一边数组,找到第一个大于target的元素,返回该元素的下标即可。查找一个数在不在我们可以用简单二分来解决,但是这道题涉及到如果不存在,需要返回待插入的位置,所以简单二分是解决不了的。因为数组是排序的,所以应该插入的位置就是target插入之后,依旧满足数组是有序的。原创 2025-01-13 21:54:45 · 302 阅读 · 0 评论 -
二分查找算法——x的平方根
我们可以分析x和结果之间的关系,结果一定在1~x/2之间。然后我们仔细观察,这个区间还存在二段性:结果会将区间分为两部分,结果的左边包含结果,它的平方一定是小于等于x的;结果的右边区间平凡一定是大于x的。我们只需要从1开始遍历,然后判断该值的平方等不等于目标值x。我们仔细观察这个区间的划分,是不是有点像之前的查找区间的右端点。我们可以使用查找区间的右端点来解决。题目还是很简单的,就是对一个数进行开平方,返回的结果需要向下取整。因为我们查找的区间是[1,x/2],所以对于当x<=1,需要特殊判断。原创 2025-01-13 16:41:58 · 398 阅读 · 0 评论 -
二分查找算法——在排序数组中查找元素的第一位置和最后一个位置
时间复杂度:最坏的情况就是数组中没有目标值,此时我就会遍历一遍数组,所以时。原创 2025-01-12 15:46:03 · 706 阅读 · 0 评论 -
二分查找算法——二分查找
3次,剩下n/8……进行x次之后,剩余1个数,n/2^x = 1,2^x = n,解得,x = log n。那么之所以有二分查找,而没有三分、四分查找算法的原因是因为,二分这样的舍弃行为的时间复杂度是很优秀的,比其他的分割方式都要优秀。如果其小于目标值,说明可以舍弃这个数,而数组是有序(升序)的,当前数的左边区间的所有数一定小于该数,也就一定目标值,所以我们可以一次舍弃到一个区间。因为区间的值都是未知的,即使最后区间只有一个数->right == left,那个数也是未知的,所以我们也要进行判断,原创 2025-01-07 23:04:22 · 389 阅读 · 0 评论 -
滑动窗口——最小覆盖子串
需要注意的是:如果字符串t包含重复字符,比如"aaac",那么在s中寻找子串的时候必须包含所有的字符,不是说同样的字符出现一次就行了。统计子串中的字符,当哈希表中出现了字符串t的所有字符之后,就记录此时子串的起始位置和长度。在进行滑动窗口之前,我们要记录哈希表mp_t的size,因为在滑动窗口过程中,mp_t会插入元素,导致size变化,所以我们要提前记录一下。空间复杂度:在该过程中,需要用到哈希表来存储数据,但是存储的都是字母,所以空间可以算是常数级的,空间复杂度为O(1).继续判断,重复该过程。原创 2025-01-07 20:56:32 · 569 阅读 · 0 评论 -
滑动窗口——串联所有单词的子串
然后我们将words中的两个字符串看作两个字符,那么s中的字符串也可以根据分组看成若干字符,这时,该题就转换成了昨天的那道题——找出所有的异位词,找出一个子区间,是由words组成的即可。判断的逻辑,当子区间的长度大于words所有字符的和的时候就需要出窗口了,但是我们这里没有必要用子区间的所有长度与words总长度比较,只需用right-left+1与总长度比较即可。题目要求:找到s中的一段连续的子串,该子串是由words中的所有字符串随机排列组合起来的,但是每一个字符串内部的顺序是不变的。原创 2025-01-05 21:39:34 · 798 阅读 · 0 评论 -
滑动窗口——找到字符串中所有字母异位词
然后判断子串的哈希表2和p的哈希表1是否星等,如果相等,则将这段区间的起始位置left记录下来,然后将left位置的元素从哈希表2中删除,然后left++,再让right++,将right位置的元素插入哈希表中,重复这个过程,直到right走到结尾。我们可以先用哈希表1将p字符串的元素都存储起来,然后在遍历子串的时候,将子串的内容放到另一个哈希表2中,然后判断两个哈希表对应元素出现的次数是否相等,如果相等,则就说明它们是异位词;不管我们的算法原理如何,一定是要判断两个单词是否为异位词的,那么要怎么判断呢?原创 2025-01-05 12:29:40 · 922 阅读 · 0 评论 -
滑动窗口——水果成篮
如果你已经摘了两种水果,下一颗树的水果是第三种,此时你就不能再采摘了。[1,2,1]表示有三棵果树,有两种类型1和2.我们接下来摘水果,从第一个位置摘占了一个篮子,接着从第二个位置摘也占了一个篮子,等到第三个的时候,不是新的种类,可以放到篮子里。我们从示例中得出总结,这道题其实就在让我们找数组的一段子区间,该子区间中元素种类不能超过2 且是最长的。方法:固定一个左边界left,然后枚举有边界,同时我们要记录当前区间的元素种类,当种类大于2时,此时就不必枚举了,让左边界++,重新开始枚举。原创 2025-01-04 11:58:06 · 616 阅读 · 0 评论 -
滑动窗口——将x减到0的最小的操作数
因为当前[left,right]区间已经满足要求了即区间和<=tol-x,那么就算你重新从left开始走,依旧会走到那个地方,这是一定的。题目还是很简单的,我们只需要每次在数组的左边或者右边选一个数,让x减去它,然后重复这个过程,如果x恰好可以减到0,那么就返回最小的操作次数;这道题还是有很多细节需要处理:当我们的目标值即最长的子区间的和小于0时,说明该区间不存在,即x不可能减小到0,此时返回-1即可。找出满足的区间即可。那么我们可以将问题转换一下,既然左右的和为x,那么中间的和就等于数组的和。原创 2025-01-02 18:36:06 · 720 阅读 · 0 评论 -
滑动窗口——最大连续1的个数3
时间复杂度:left和right在最坏的情况下都会遍历依次数组,所以是2n,整体上时间复杂度为O(N).空间复杂度:O(1).原创 2025-01-01 19:48:57 · 766 阅读 · 0 评论 -
滑动窗口——无重复字符的最长子串
时间复杂度:从整体上看,需要两个指针,left和right,left依次遍历字符串,right在固定好left的前提下也要遍历一边字符串,所以时间复杂度为O(N^2)。题目说的是没有重复字符的最长子串,你已经有了重复字符,你right就算走到结尾,这个子串也不可能是最终结果!判断一个字符是否重复出现,我们只需要把每一个字符放到一个哈希表中即可,如果一个字符出现的次数>1,说明就重复出现了。重复字符有可能不是左端点,这时就算你left++,新的子串中依旧有重复字符,这个子串也不可能是答案。原创 2025-01-01 11:04:32 · 714 阅读 · 0 评论 -
滑动窗口——长度最小的子数组
题目还是很好理解的,我们只需要找到一段连续的子数组,让其的和大于等于target即可,但要求是要找到最短的子数组。需要注意,这里的子数组一定得是连续的,比如示例一:[2,3,2],虽然满足>target,但其并不是连续的子数组。时间复杂度:首先我们枚举出所有的子数组需要O(N^2),然后在遍历每一个子数组,求出sum,这个是O(N),所以整体的时间复杂度为O(N^3)。我们可以枚举出所有的子数组,然后遍历子数组求出数组的和sum,判断sum是否满足>=target,在这个过程中更新满足要求的最短长度即可。原创 2024-12-31 10:50:26 · 918 阅读 · 0 评论 -
双指针——四数之和
题目中也要求不重复,与三数之和的重复判定一样,只要四元组中元素相同就算重复。对于三数之和,我们先固定一个数b,然后在剩下的区间内借助双指针算法,找出两个数和为target-a-b的二元组即可。我们先固定一个数a,然后就是在剩下的区间内找出三个数之和为target-a的三元组,这不就是三数之和么。需要注意的是,这里在计算newTarget时有可能会数据溢出,所以要进行类型转换,避免溢出。2、去重,在a、b、以及left和right的选取都要避免选取重复值,同时也要避免越界。这里的解决办法和三数之和是一样的。原创 2024-12-29 12:03:51 · 280 阅读 · 0 评论 -
双指针——三数之和
当在left~right区间内找到了和为-a的二元组之后,left++,right--,如果该位置的值与之前的值相同,那就没必要在判断了,直接从下一个不相等的位置开始查找。选a的小优化:因为数据是递增的,且left永远再a的下一个位置。所以当a>0之后,left、right位置的数和永远为正数,三个正数和不可能为0,所以a应该原创 2024-12-28 19:20:08 · 855 阅读 · 0 评论 -
双指针——查找总价格为目标值的两个商品
需要注意的是,如果我们直接在循环内返回的话,在leetcode上就会报错:不是所有的路径都有返回值。因为它不能保证你在循环内部就会返回结果,如果结束了循环,外面并没有return语句,此时就会报错。暴力解法的话我们可以枚举出所有的情况,然后判断是否等于target。我们来分析时间复杂度:最坏情况下,left和right下一次就会相遇,此时遍历了一遍数组,所以时间复杂度为O(N),空间复杂度为:O(1).我们让两个指针分别指向数组的开始和结尾,然后判断相加之后的结果,再根据单调性选择指针的移动。原创 2024-12-27 21:40:05 · 418 阅读 · 0 评论 -
双指针——有效三角形的个数
当a+b<=c时,此时right移动没有意义,因为不管right怎么移动,剩下的值都比现在的小,所以更不可能构成三角形了,此时该区间内不会构成三角形,我们要让left++,在下一个区间内继续查找。但是我们可以对这个判断逻辑进行优化,我们可以先对三个数进行排序,a<=b<=c,这样我们只需要判断最小的两个数a+b>c即可。2.a+b<=c.情况不同,我们的处理办法也不同。我们分析一下时间复杂度:三层循环,时间复杂度为O(N^3),再加上判断是否为三角形所以整体的时间复杂度为O(3*N^3)。原创 2024-12-26 22:43:55 · 325 阅读 · 0 评论 -
双指针——盛最多水的容器
题目的文字描述比较难懂,所以我们看实例1的图来理解:其实height数组存储的每一个数都是每一个位置上墙的高度,我们需要求出这些墙所能存储的最多的水。然后我们将这个规律推广到整个区间,我们用left和right分别指向数组的左右边界,然后记录当前的V,接着让矮墙++/--,接着计算新的V,一直重复该过程,知道left与right相遇。在一段区间中,当前区间的V一定大于由矮的墙与其他墙所围成的V。因为V = h*w,矮墙往区间里面遍历的时候,w一定减小,而h要么减小要么不变,所以V一定减小。原创 2024-12-25 22:31:03 · 648 阅读 · 0 评论 -
双指针——快乐数
我们要判断一个数是不是快乐数要通过它的三个性质来进行判断。这个数会一直变化,由它的各个位的平方和重新构成这个数。如果这个数在变化的过程中变成了1,那么就是快乐数;如果陷入了循环,一直变不到1,就说明不是快乐数。我们看到上面的情况图有没有联想到之前学习链表的一道题——带环链表。所以,对于一个数n来说有两种情况:1、在进行若干次变换后变成了1;但其实,我们可以将第一种也归为是进入循环的一种,只不过每一个位置都是1.因为我们需要频繁求一个数的每个位的平方和,所以我们将其写成一个函数。原创 2024-12-25 21:49:38 · 337 阅读 · 0 评论