Skip to content

2026

About 3042 wordsAbout 10 min

2026-02-23

2026年08月

xxx

2026年07月

3014. 输入单词需要的最少按键次数 I

20260730

题目给定一字符串 word,设 word 的长度为 n,k = n / 8(下取整)

image-20260730231917472

ans =8 * (1+2+...+k) + n%8 * k+1

3016. 输入单词需要的最少按键次数 II

排序不等式

将出现次数多的放在前面。这样就可以少按一下。

int[] cnt =new int[26];
for(char ch: word.toCharArray()){
  cnt[ch-'a']++;
}
for(int i =0;i<26;i++){
  ans += cnt[25-i] * (i%8 +1);
}

2685. 统计完全连通分量的数量

连通分量:如果子图中任意两个顶点之间都存在路径,并且子图中没有任何一个顶点与子图外部的顶点共享边,则称为连通分量。

完全联通分量:如果联通分量中没对节点之间都存在一条边,则称为完全两通分量。

142. 环形链表 II

Details

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos-1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

示例 1:

img

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

img

输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

img

输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。

提示:

  • 链表中节点的数目范围在范围 [0, 104]
  • -105 <= Node.val <= 105
  • pos 的值为 -1 或者链表中的一个有效索引

【图解】一张图秒懂环形链表 II,Floyd 判圈算法(Python/Java/C++/C/Go/JS)

参考灵神的题解, 这里只是做自己的理解。

8cd6211a-63a1-45d5-9a52-58be723e3156

设从头结点到入口的距离是 a,从入口到相遇点的距离为 b,相遇见到入口的距离为 c,如图

环长 = b+cb+c

慢指针移动的距离 = a+ba + b

快指针移动的距离 =a+b+k(b+c)a + b + k(b+c),k 表示在环中移动的次数

那么就有等式: 2(a+b)=a+b+k(b+c)2(a+b) = a+ b+k(b+c)

=> 2a+2b=a+b+b+c+(k1)(b+c)2a + 2b = a + b + b + c + (k-1)(b+c)

=> $a - c = (k-1)(b+c) $ => 这意味着什么?

slow 从相遇点出发,head 从头结点出发,走 c 步后,slow 在入口,head 到入口的距离也恰好是环长的倍数,继续走,两者必然会在入口相遇。

2026年06 月

1967. 作为子字符串出现在单词中的字符串数目TODO

Details

给你一个字符串数组 patterns 和一个字符串 word ,统计 patterns 中有多少个字符串是 word 的子字符串。返回字符串数目。

子字符串 是字符串中的一个连续字符序列。

示例 1:

输入:patterns = ["a","abc","bc","d"], word = "abc"
输出:3
解释:
- "a" 是 "abc" 的子字符串。
- "abc" 是 "abc" 的子字符串。
- "bc" 是 "abc" 的子字符串。
- "d" 不是 "abc" 的子字符串。
patterns 中有 3 个字符串作为子字符串出现在 word 中。

示例 2:

输入:patterns = ["a","b","c"], word = "aaaaabbbbb"
输出:2
解释:
- "a" 是 "aaaaabbbbb" 的子字符串。
- "b" 是 "aaaaabbbbb" 的子字符串。
- "c" 不是 "aaaaabbbbb" 的字符串。
patterns 中有 2 个字符串作为子字符串出现在 word 中。

示例 3:

输入:patterns = ["a","a","a"], word = "ab"
输出:3
解释:patterns 中的每个字符串都作为子字符串出现在 word "ab" 中。

提示:

  • 1 <= patterns.length <= 100
  • 1 <= patterns[i].length <= 100
  • 1 <= word.length <= 100
  • patterns[i]word 由小写英文字母组成

题目简单,就是判断 pattern 中给出的字符串中有几个是 word 的子串,第一种暴力求解, 判断 word.contains(s),第二种是自动机,也是需要学习的内容。

两种方法:暴力 / AC 自动机(Python/Java/C++/Go)

2095. 删除链表的中间节点

Details

给你一个链表的头节点 head删除 链表的 中间节点 ,并返回修改后的链表的头节点 head

长度为 n 链表的中间节点是从头数起第 ⌊n / 2⌋ 个节点(下标从 0 开始),其中 ⌊x⌋ 表示小于或等于 x 的最大整数。

  • 对于 n = 12345 的情况,中间节点的下标分别是 01122

示例 1:

img

输入:head = [1,3,4,7,1,2,6]
输出:[1,3,4,1,2,6]
解释:
上图表示给出的链表。节点的下标分别标注在每个节点的下方。
由于 n = 7 ,值为 7 的节点 3 是中间节点,用红色标注。
返回结果为移除节点后的新链表。

示例 2:

img

输入:head = [1,2,3,4]
输出:[1,2,4]
解释:
上图表示给出的链表。
对于 n = 4 ,值为 3 的节点 2 是中间节点,用红色标注。

示例 3:

img

输入:head = [2,1]
输出:[2]
解释:
上图表示给出的链表。
对于 n = 2 ,值为 1 的节点 1 是中间节点,用红色标注。
值为 2 的节点 0 是移除节点 1 后剩下的唯一一个节点。

提示:

  • 链表中节点的数目在范围 [1, 105]
  • 1 <= Node.val <= 105

主要思路:

看到链表的中间节点,就应该想到快慢指针, 就不用模拟去计算链表的长度。

让快指针先走一步,这样的话,慢指针的位置刚好是在中间节点的前一个,然后删除到慢指针后一个节点就可以了。

龟兔赛跑(Python/Java/C++/C/Go/JS/Rust)

扩展链表的遍历:

  • 链表(链式存储)基本原理
  • 增:
    • 在头节点加:p.next = head; head = p;
    • 在中间加:p.next = s.next; s.next = p;
    • 在尾部加: tail.next = p; p.next = null;
  • 删:
    • 在头部删: return head.next;
    • 在中部删:s.next = s.next.next;
    • 在尾部删:s.next = null;
  • 查:
    • head.next != null 遍历到最后一个节点就停止了,不会处理最后一个节点,循环结束,head 指向最后一个节点
    • head != null 遍历到最后一个节点之后的 null 节点, 会处理所有节点,包括最后一个节点,循环结束时,head 执行 null

2026年04 月

2033. 获取单值网格的最小操作数

Details

给你一个大小为 m x n 的二维整数网格 grid 和一个整数 x 。每一次操作,你可以对 grid 中的任一元素 x x

单值网格 是全部元素都相等的网格。

返回使网格化为单值网格所需的 最小 操作数。如果不能,返回 -1

示例 1:

img

输入:grid = [[2,4],[6,8]], x = 2
输出:4
解释:可以执行下述操作使所有元素都等于 4 : 
- 2 加 x 一次。
- 6 减 x 一次。
- 8 减 x 两次。
共计 4 次操作。

示例 2:

img

输入:grid = [[1,5],[2,3]], x = 1
输出:5
解释:可以使所有元素都等于 3 。

示例 3:

img

输入:grid = [[1,2],[3,4]], x = 2
输出:-1
解释:无法使所有元素相等。

中位数贪心及其证明

大概的意思就是,当全部元素为数组的中位数的时候,操作数最小,上面证明。

当x=2时,我们不能把2,5都变成一个数,因为偶数只能变成偶数,奇数只能变成奇数,一般的,对于整数k,我们有:

(grid[i][j]+kx)modx=grid[i][j]modx(grid[i][j] + kx) mod x = grid[i][j] mod x

所以操作后,grid[i][j] mod x 是不变的,每个数取模x的结果必须都一样,才能变成同一个数,否则无解。

2026年02 月

1461. 检查一个字符串是否包含所有长度为 K 的二进制子串

Details

给你一个二进制字符串 s 和一个整数 k 。如果所有长度为 k 的二进制字符串都是 s 的子串,请返回 true ,否则请返回 false

示例 1:

输入:s = "00110110", k = 2
输出:true
解释:长度为 2 的二进制串包括 "00","01","10" 和 "11"。它们分别是 s 中下标为 0,1,3,2 开始的长度为 2 的子串。

示例 2:

输入:s = "0110", k = 1
输出:true
解释:长度为 1 的二进制串包括 "0" 和 "1",显然它们都是 s 的子串。

示例 3:

输入:s = "0110", k = 2
输出:false
解释:长度为 2 的二进制串 "00" 没有出现在 s 中。

提示:

  • 1 <= s.length <= 5 * 105
  • s[i] 不是'0' 就是 '1'
  • 1 <= k <= 20

这道题要求判断字符串 s 是否包含所有长度为 k 的二进制子串。下面逐步解析代码: 核心思路 长度为 k 的二进制串总共有 2^k 个(从 000...0 到 111...1)。代码用滑动窗口 + 位运算来高效地枚举 s 中所有长度为 k 的子串,检查是否覆盖了全部 2^k 种情况。 逐行解析

  1. 预处理 final int MASK = (1 << k) - 1;
  • 1 << k 就是 2^k,例如 k=3 时为 8(二进制 1000)。
  • 减 1 得到 0111,即低 k 位全为 1 的掩码。
  • 作用:后面用来截取整数的低 k 位,丢弃高位多余的比特。 boolean[] has = new boolean[1 << k];
  • 大小为 2^k 的布尔数组,has[x] 表示值为 x 的长度为 k 的二进制子串是否已经出现过。 int cnt = 0; // 已经收集到的不同子串数量 int x = 0; // 当前滑动窗口对应的整数值
  1. 滑动窗口遍历 for (int i = 0; i < s.length() && cnt < (1 << k); i++) {
  • 遍历字符串,同时如果已经集齐所有 2^k 种子串就提前退出(剪枝优化)。
  1. 位运算更新窗口 x = (x << 1 & MASK) | (ch & 1); 这是最关键的一行,拆解如下:
步骤操作含义
x << 1左移一位为新字符腾出最低位
& MASK与掩码只保留低 k 位,丢掉最高位(相当于窗口左边的字符滑出)
ch & 1字符转数字'0' 的 ASCII 码末位是 0,'1' 的末位是 1
| (ch & 1)或运算把新字符放到最低位(窗口右边加入新字符)
举例:k=3,MASK=0b111,当前 x=0b101(5),新字符 '0':
  • 0b101 << 1 = 0b1010
  • & 0b111 = 0b010(最高位的 1 被丢弃)
  • | 0 = 0b010(2)
  • 窗口从 "101" 滑动到 "010",完全正确。
  1. 记录新子串 if (i >= k - 1 && !has[x]) { has[x] = true; cnt++; }
  • i >= k - 1:确保窗口已经积累了 k 个字符(前 k-1 个位置窗口还没满)。
  • !has[x]:如果这个子串没见过,标记并计数。
  1. 最终判断 return cnt == (1 << k);
  • 收集到的不同子串数恰好等于 2^k,说明全部覆盖。 复杂度
  • 时间:O(n),遍历一次字符串
  • 空间:O(2^k),布尔数组大小 对比朴素做法 朴素做法是对每个子串调用 substring 再转整数,每次 O(k);而这里用位运算滑动窗口,每次只需 O(1) 就能从上一个窗口推导出下一个窗口的值,效率更高。

求求了,快滚去学习!!!

求求了求求了,快去学习吧!

【LeetCode】贪心算法
【LeetBook】数组和字符串

不知道方向的时候,可以多看看书,书会给你指明下一步该干什么,加油!