2024-10-30:或值至少 K 的最短子数组 I。用 go 语言,给定一个非负整数数组 nums 和一个整数 k,我们需要判断数组中是否存在一个最短的非空子数组,使得该子数组所有元素的按位或(OR)运
2024-10-30:或值至少 K 的最短子数组 I。用 go 语言,给定一个非负整数数组 nums 和一个整数 k,我们需要判断数组中是否存在一个最短的非空子数组,使得该子数组所有元素的按位或(OR)运算结果至少为 k。如果找到了这样的子数组,返回其长度;如果不存在,则返回 -1。
输入:nums = [1,2,3], k = 2。
输出:1。
解释:
子数组 [3] 的按位 OR 值为 3 ,所以我们返回 1 。
注意,[2] 也是一个特别子数组。
答案 2024-10-30:
题目来自 leetcode3095。
大体步骤如下:
代码逻辑分析
1.初始化:
minLen
被设置为math.MaxInt32
,用于存储找到的最短子数组的长度。n
是数组nums
的长度。
2.解决方案 1:
对于每一个索引
i
从0
到n-1
,表示当前子数组的结束位置。对于每一个
j
从i
递减到0
,表示当前子数组的起始位置。检查从
j
到i
这段子数组的按位或结果,调用isSpecial
函数。如果返回的结果满足大于等于
k
,则更新minLen
为当前子数组长度i-j+1
的最小值。最后,如果没有找到满足条件的子数组,返回
-1
;否则返回minLen
。
3.isSpecial 函数:
接受数组
nums
和子数组的起始、结束索引j
、i
,以及目标值k
。初始化结果
res
为0
。遍历子数组,计算位或结果
res |= nums[idx]
。最后返回一个布尔值,判断
res
是否大于等于k
。
4.解决方案 2:
该方法做了优化,先检查当前元素
nums[i]
是否已经大于等于k
,如果是,则直接返回1
,因为单独的元素就满足了条件。同样遍历
j
,更新nums[j]
为nums[j] | nums[i]
。并检查是否满足按位或条件。如果找到了满足条件的子数组,则更新
minLen
。最后根据
minLen
的最终值返回结果。
时间复杂度
解决方案 1:最坏情况下,外层循环和内层循环都是进行
O(n^2)
的遍历。解决方案 2:外层循环为
O(n)
,内层循环的最坏情况下为O(n)
,因此在某些情况下也可能达到O(n^2)
的复杂度。最终时间复杂度:最坏情况为
O(n^2)
。
空间复杂度
两种解决方案都只使用了常量级的额外空间,主要是用于存储变量
minLen
和中间结果res
,以及输入数组nums
本身。没有使用额外的数据结构来增加空间开销。最终空间复杂度:
O(1)
。
总结
代码通过两种方式实现了目标,虽然最坏情况下时间复杂度达到 O(n^2)
但在实际操作中,尤其是对于较小的输入数组,可能表现良好。空间复杂度保持在常数级别,确保了算法的高效性。
Go 完整代码如下:
Rust 完整代码如下:
版权声明: 本文为 InfoQ 作者【福大大架构师每日一题】的原创文章。
原文链接:【http://xie.infoq.cn/article/01890d278fa7a3695faf1d45e】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论