classSolution: defminimumSubarrayLength(self, nums: List[int], k: int) -> int: ans = +inf for i inrange(len(nums)): temp = nums[i] if temp >= k: return1 for j inrange(i+1,len(nums)): temp |= nums[j] if temp >= k: ans = min(ans,j-i+1) break return ans if ans != +inf else -1
思路:
暴力枚举所有的子数组,找到其中满足或值大于等于 k 的最短子数组。
代码二:暴力优化
超出时间限制 717 / 718 个通过的测试用例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution: defminimumSubarrayLength(self, nums: List[int], k: int) -> int: ans = +inf res = 0 for i,j inenumerate(nums): if j >= k: return1 res |= j if res >= k: res = j for m inrange(i-1,-1,-1): res |= nums[m] if res >= k: ans = min(ans,i-m+1) break return ans if ans != +inf else -1
classSolution: defminimumSubarrayLength(self, nums: List[int], k: int) -> int: ans = +inf for i,j inenumerate(nums): if j >= k: return1 for m inrange(i-1,-1,-1): nums[m] |= nums[i] if nums[m] >= k: ans = min(ans,i-m+1) break return ans if ans != +inf else -1
思路:
还是从后往前的思路,只不过是更新的数组的值,但是时间复杂度:O(n^2)
还是超时。(ps:为什么都是从后往前,代码三比代码二通过的测试用例要少呢?)
代码四:LogTrick
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution: defminimumSubarrayLength(self, nums: List[int], k: int) -> int: ans = +inf for i,j inenumerate(nums): if j >= k: return1 for m inrange(i-1,-1,-1): if nums[m] | j == nums[m]: #每次OR运算数字都会变大,倘如没有变大就退出 break nums[m] |= j if nums[m] >= k: ans = min(ans,i-m+1) break return ans if ans != +inf else -1
时间复杂度:O(nlogU) 其中 n 是 nums 的长度, U=max(nums) 。由于题目范围二进制数对应集合的大小不会超过 29,因此在 OR 运算下,每个数字至多可以增大 29 次。总体上看,二重循环的总循环次数等于每个数字可以增大的次数之和,即 O(nlogU)。 空间复杂度:O(1) 。
代码五:滑动窗口+栈(理解感觉吃力,使用更难,瞻仰灵神)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution: defminimumSubarrayLength(self, nums: List[int], k: int) -> int: ans = inf left = bottom = right_or = 0 for right, x inenumerate(nums): right_or |= x while left <= right and nums[left] | right_or >= k: ans = min(ans, right - left + 1) left += 1 if bottom < left: # 重新构建一个栈 for i inrange(right - 1, left - 1, -1): nums[i] |= nums[i + 1] bottom = right right_or = 0 return ans if ans < inf else -1