leetcode力扣刷题系列——【找到按位或最接近 K 的子数组】

题目

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

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

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

示例 1
输入:

nums = 1,2,4,5, k = 3
输出

0
解释:

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

示例 2:

输入:

nums = 1,3,1,3, k = 2
输出:

1
解释:

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

示例 3:
输入:

nums = 1, k = 10

输出:

9
解释:

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

提示:

1 <= nums.length <= 105

1 <= numsi <= 109

1 <= k <= 109

答案

我的方法

方法有问题,这道题在力扣中属于难题,对我而言也不简单,我就是简单的先找到所有的子列表,再找到所有的or值,在进行绝对值的运算,这样子确实简单易懂,但是一旦nums足够大,我们的程序就会超出内存大小。

今天也是没有完成今天的题目,还是因为我太菜啦,想不到更牛的方法,所以今天还是分享一下官方大大的解题思路和方法吧。

python 复制代码
class Solution(object):
    def minimumDifference(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        # 获取数组中所有子数组的值
        subnums=[]
        result = []
        for i in range(len(nums)):
            for j in range(i,len(nums)):
                subnum = nums[i:j+1]
                subnums.append(subnum)
        # 算出每一个或运算的值
        for sublist in subnums:
            if len(sublist) == 1:
                result.append(sublist[0])
            else:
                or_result = sublist[0]
                for num in sublist[1:]:
                    or_result = or_result | num
                result.append(or_result)
        absnums = [abs(num - k) for num in result]
        return min(absnums)

注:我写的方法没啥用,并没有能通过测试

官方大大的方法
思路与算法

题目给定一个数组 nums 和一个整数 k。我们需要找到 nums 的一个非空子数组,要求其所有元素的或运算结果与 k 值尽可能接近。

根据或运算的性质,当我们固定子数组的右端点,不断地向左延伸左端点时,子数组或运算结果逐渐增加,并且结果种类数不超过 log(max(nums))+1 种。因为或运算结果每次增加对应于二进制表示中某些位上由 0 变为 1,因此增加的种类数受到数值范围的限制。

因此,我们从左到右遍历 nums,并在过程中记录每个二进制上的 1 出现的最晚的位置。这些位置用于我们在延伸左端点时,遍历所有种类的或运算结果。具体的,我们用 bits_max_posj 来表示第 j 个二进制为 1 出现的最晚位置,在固定右端点后,将所有的二元组 (bits_max_posj,j) 从大到小排序,然后依次遍历这些二元组。遍历时将或运算结果与 2^j做或运算,得到新的结果,并计算其与 k 的差值。最终答案取所有差值的最小值。

需要注意的是,对于不同的 j,其 bits_max_posj 可能相同,在计算区间或运算结果时需要将它们都考虑到,因此这里需要双指针去更新或运算结果。

代码

python 复制代码
n = len(nums)
        bits_max_pos = [-1] * 31
        res = inf
        
        for i in range(n):
            for j in range(31):
                if nums[i] >> j & 1:
                    bits_max_pos[j] = i
            pos_to_bit = [(bits_max_pos[j], j) for j in range(31) if bits_max_pos[j] != -1]
            pos_to_bit.sort(reverse = True, key = lambda x: x[0])
            
            j, val = 0, 0
            while j < len(pos_to_bit):
                p = j
                while j < len(pos_to_bit) and pos_to_bit[j][0] == pos_to_bit[p][0]:
                    val |= 1 << pos_to_bit[j][1]
                    j += 1
                res = min(res, abs(val - k))
        
        return res

作者:力扣官方题解
我是链接哦

来源:力扣(LeetCode)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

相关推荐
stolentime1 小时前
洛谷P10515 转圈题解
c++·算法·数学建模·贪心算法
和裕2 小时前
蜂窝板 vs 七层瓦楞重型纸箱:大件工业设备运输性能与成本全对比
大数据·运维·网络·人工智能·算法
衡石科技2 小时前
Data_Agent记忆机制与经验复用衡石分析智能体会话记忆与长期学习技术解析
人工智能·科技·学习·算法·企业级bi
shirsl4 小时前
算法 Day 2 滑动窗口 + 栈 / 单调栈
开发语言·python·算法
土司大王5 小时前
LeetCode hot100 回溯专题总结:Java 通用模板、决策树模型
java·算法·leetcode·决策树
2601_962218615 小时前
万象生鲜系统订单全生命周期状态同步技术实现业务可视
大数据·数据库·人工智能·python·算法
那年窗外下的雪.5 小时前
AIDC 学习日志|第 22 天|All-Active/Single-Active 故障演练设计
服务器·网络·学习·算法·哈希算法
wzdark6 小时前
基于启发式搜索的最优路径规划算法研究4
算法
l1t6 小时前
用superpi、tinypi、tpi等工具计算圆周率的比较
c语言·算法
小智老师PMP6 小时前
2026PMP第八版新纲深度解读|从流程管控到价值交付,核心考点全迭代
人工智能·职场和发展·软件工程·制造·敏捷流程