LeetCode 题解工作台

找到按位或最接近 K 的子数组

给你一个数组 nums 和一个整数 k 。你需要找到 nums 的一个 子数组 ,满足子数组中所有元素按位或运算 OR 的值与 k 的 绝对差 尽可能 小 。换言之,你需要选择一个子数组 nums[l..r] 满足 |k - (nums[l] OR nums[l + 1] ... OR nums[r…

category

4

题型

code_blocks

5

代码语言

hub

3

相关题

当前训练重点

困难 · 二分·搜索·答案·空间

bolt

答案摘要

根据题目描述,我们需要求出数组 下标 到 的元素的按位或运算的结果,即 $\textit{nums}[l] \lor \textit{nums}[l + 1] \lor \cdots \lor \textit{nums}[r]$。其中 表示按位或运算。 如果我们每次固定右端点 ,那么左端点 的范围是 $[0, r]$。每次移动右端点 ,按位或的结果只会变大,我们用一个变量 记录当前的按…

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 二分·搜索·答案·空间 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

给你一个数组 nums 和一个整数 k 。你需要找到 nums 的一个 子数组 ,满足子数组中所有元素按位或运算 OR 的值与 k 的 绝对差 尽可能  。换言之,你需要选择一个子数组 nums[l..r] 满足 |k - (nums[l] OR nums[l + 1] ... OR nums[r])| 最小。

请你返回 最小 的绝对差值。

子数组 是数组中连续的 非空 元素序列。

 

示例 1:

输入:nums = [1,2,4,5], k = 3

输出:0

解释:

子数组 nums[0..1] 的按位 OR 运算值为 3 ,得到最小差值 |3 - 3| = 0

示例 2:

输入:nums = [1,3,1,3], k = 2

输出:1

解释:

子数组 nums[1..1] 的按位 OR 运算值为 3 ,得到最小差值 |3 - 2| = 1

示例 3:

输入:nums = [1], k = 10

输出:9

解释:

只有一个子数组,按位 OR 运算值为 1 ,得到最小差值 |10 - 1| = 9 。

 

提示:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 109
  • 1 <= k <= 109
lightbulb

解题思路

方法一:双指针 + 位运算

根据题目描述,我们需要求出数组 nums\textit{nums} 下标 llrr 的元素的按位或运算的结果,即 nums[l]nums[l+1]nums[r]\textit{nums}[l] \lor \textit{nums}[l + 1] \lor \cdots \lor \textit{nums}[r]。其中 \lor 表示按位或运算。

如果我们每次固定右端点 rr,那么左端点 ll 的范围是 [0,r][0, r]。每次移动右端点 rr,按位或的结果只会变大,我们用一个变量 ss 记录当前的按位或的结果,如果 ss 大于 kk,我们就将左端点 ll 向右移动,直到 ss 小于等于 kk。在移动左端点 ll 的过程中,我们需要维护一个数组 cntcnt,记录当前区间内每个二进制位上 00 的个数,当 cnt[h]cnt[h]00 时,说明当前区间内的元素在第 hh 位上都为 00,我们就可以将 ss 的第 hh 位设置为 00

时间复杂度 O(n×logM)O(n \times \log M),空间复杂度 O(logM)O(\log M)。其中 nnMM 分别是数组 nums\textit{nums} 的长度和数组 nums\textit{nums} 中元素的最大值。

相似题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution:
    def minimumDifference(self, nums: List[int], k: int) -> int:
        m = max(nums).bit_length()
        cnt = [0] * m
        s = i = 0
        ans = inf
        for j, x in enumerate(nums):
            s |= x
            ans = min(ans, abs(s - k))
            for h in range(m):
                if x >> h & 1:
                    cnt[h] += 1
            while i < j and s > k:
                y = nums[i]
                for h in range(m):
                    if y >> h & 1:
                        cnt[h] -= 1
                        if cnt[h] == 0:
                            s ^= 1 << h
                i += 1
                ans = min(ans, abs(s - k))
        return ans
speed

复杂度分析

指标
时间Depends on the final approach
空间Depends on the final approach
psychology

面试官常问的追问

外企场景
  • question_mark

    The candidate uses binary search effectively to narrow down the possible range of OR values.

  • question_mark

    They demonstrate a solid understanding of bitwise operations and their implications for array manipulation.

  • question_mark

    The candidate proposes an efficient way to track the OR values for multiple subarrays, possibly with dynamic programming or a segment tree.

warning

常见陷阱

外企场景
  • error

    Not considering the need for efficient range queries can lead to suboptimal performance.

  • error

    Failing to recognize the potential optimization of binary search over the OR values might result in slower solutions.

  • error

    Misunderstanding the problem's constraints may lead to an approach that doesn't scale with larger arrays.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Modify the problem to find the subarray that minimizes the sum of bitwise OR values across subarrays.

  • arrow_right_alt

    Introduce multiple target values for k, requiring the solution to handle multiple queries in the same problem.

  • arrow_right_alt

    Optimize the solution further by reducing the space complexity, potentially eliminating the need for dynamic programming.

help

常见问题

外企场景

找到按位或最接近 K 的子数组题解:二分·搜索·答案·空间 | LeetCode #3171 困难