滑动窗口 | 按位单独处理 | 字符计数
字数统计: 1k字 | 阅读时长: 4分
摘要: 综合题:滑动窗口 + 按位单独处理 + 字符计数
【对算法,数学,计算机感兴趣的同学,欢迎关注我哈,阅读更多原创文章】
我的网站:潮汐朝夕的生活实验室
我的公众号:算法题刷刷
我的知乎:潮汐朝夕
我的github:FennelDumplings
我的leetcode:FennelDumplings
各位好,今天我们来看一个综合题,在滑动窗口中维护各个二进制位对应的计数,这种计数有点像字符串上滑动窗口时的字符计数,也有点像是按位单独处理的技巧,可以理解为将两种思想结合了一下。
按位单独处理,以及在滑动窗口内维护字符计数这两种思想上周都有文章解决过各自的问题,可以参考:
题目
给你一个 非负 整数数组 nums 和一个整数 k 。
如果一个数组中所有元素的按位或运算 OR 的值 至少 为 k ,那么我们称这个数组是 特别的 。
请你返回 nums 中 最短特别非空子数组的长度,如果特别子数组不存在,那么返回 -1 。
示例 1:
输入:nums = [1,2,3], k = 2
输出:1
解释:
子数组 [3] 的按位 OR 值为 3 ,所以我们返回 1 。示例 2:
输入:nums = [2,1,8], k = 10
输出:3
解释:
子数组 [2,1,8] 的按位 OR 值为 11 ,所以我们返回 3 。示例 3:
输入:nums = [1,2], k = 0
输出:1
解释:
子数组 [1] 的按位 OR 值为 1 ,所以我们返回 1 。
提示:
1 | 1 <= nums.length <= 2e5 |
题解
算法: 滑动窗口
由按位或的性质,x | y >= x,因此当固定子数组左端点 l 时,随着右端点 r 推进,按位或的结果是单调递增的。因此当 r 推进到某个位置,按位或的结果首次不小于 k,此时的窗口长度 r - l + 1 就对应了左端点为 l 时的最短的满足条件的窗口。由此我们可以设计以滑动窗口为基础的算法。
在推进滑动窗口时,始终维护一个类似于字符计数(元素的第 i 位为 1,则视为元素包含字符 i)的信息 cnt[i] 表示第 i 位为 1 的个数,对于给定的数据范围,有 0 <= i < 32。在判定窗口合法性时,把 cnt[i] 中计数大于 0 的位都置 1,即可得到窗口的按位或的结果,大致的代码如下:
1 | s = 0 |
至此我们可以给出最终算法:
1 | l = 0, r = -1 |
l 和 r 都只向右推进一轮,每推进一步需要遍历一次字符计数,因此总时间复杂度为 $O(nU)$,$U$ 为元素的二进制位数。
代码 (Python)
1 | def check(cnt, k): |




























