当前位置: 首页 > news >正文

位运算题目:找到最接近目标值的函数值

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
  • 解法
    • 思路和算法
    • 代码
    • 复杂度分析

题目

标题和出处

标题:找到最接近目标值的函数值

出处:1521. 找到最接近目标值的函数值

难度

8 级

题目描述

要求

函数

Winston 构造了一个如上所示的函数 func \texttt{func} func。他有一个整数数组 arr \texttt{arr} arr 和一个整数 target \texttt{target} target,他想找到让 ∣ func(arr, l, r) − target ∣ \big| \texttt{func(arr, l, r)} - \texttt{target} \big| func(arr, l, r)target 最小的 l \texttt{l} l r \texttt{r} r

返回 ∣ func(arr, l, r) − target ∣ \big| \texttt{func(arr, l, r)} - \texttt{target} \big| func(arr, l, r)target 的最小值。

注意 func \texttt{func} func 的输入参数包含 l \texttt{l} l r \texttt{r} r,满足 0 ≤ l, r < arr.length \texttt{0} \le \texttt{l, r} < \texttt{arr.length} 0l, r<arr.length

示例

示例 1:

输入: arr = [9,12,3,7,15], target = 5 \texttt{arr = [9,12,3,7,15], target = 5} arr = [9,12,3,7,15], target = 5
输出: 2 \texttt{2} 2
解释:所有可能的 [l,r] \texttt{[l,r]} [l,r] 数对包括 [[0,0],[1,1],[2,2],[3,3],[4,4],[0,1],[1,2],[2,3],[3,4],[0,2],[1,3],[2,4],[0,3],[1,4],[0,4]] \texttt{[[0,0],[1,1],[2,2],[3,3],[4,4],[0,1],[1,2],[2,3],[3,4],[0,2],[1,3],[2,4],[0,3],[1,4],[0,4]]} [[0,0],[1,1],[2,2],[3,3],[4,4],[0,1],[1,2],[2,3],[3,4],[0,2],[1,3],[2,4],[0,3],[1,4],[0,4]],Winston 得到的相应结果为 [9,12,3,7,15,8,0,3,7,0,0,3,0,0,0] \texttt{[9,12,3,7,15,8,0,3,7,0,0,3,0,0,0]} [9,12,3,7,15,8,0,3,7,0,0,3,0,0,0]。最接近 5 \texttt{5} 5 的值是 7 \texttt{7} 7 3 \texttt{3} 3,所以最小差值为 2 \texttt{2} 2

示例 2:

输入: arr = [1000000,1000000,1000000], target = 1 \texttt{arr = [1000000,1000000,1000000], target = 1} arr = [1000000,1000000,1000000], target = 1
输出: 999999 \texttt{999999} 999999
解释:Winston 输入函数的所有可能 [l,r] \texttt{[l,r]} [l,r] 数对得到的函数值都为 1000000 \texttt{1000000} 1000000,所以最小差值为 999999 \texttt{999999} 999999

示例 3:

输入: arr = [1,2,4,8,16], target = 0 \texttt{arr = [1,2,4,8,16], target = 0} arr = [1,2,4,8,16], target = 0
输出: 0 \texttt{0} 0

数据范围

  • 1 ≤ arr.length ≤ 10 5 \texttt{1} \le \texttt{arr.length} \le \texttt{10}^\texttt{5} 1arr.length105
  • 1 ≤ arr[i] ≤ 10 6 \texttt{1} \le \texttt{arr[i]} \le \texttt{10}^\texttt{6} 1arr[i]106
  • 0 ≤ target ≤ 10 7 \texttt{0} \le \texttt{target} \le \texttt{10}^\texttt{7} 0target107

解法

思路和算法

n n n 表示数组 arr \textit{arr} arr 的长度。如果枚举所有的下标对 ( l , r ) (l, r) (l,r),则时间复杂度至少是 O ( n 2 ) O(n^2) O(n2),该时间复杂度过高,需要优化。

如果子数组的右侧端点 r r r 固定,分别考虑两个左侧端点 l 1 l_1 l1 l 2 l_2 l2 对应的函数值。当 l 1 < l 2 ≤ r l_1 < l_2 \le r l1<l2r 时,记 v 1 = func ( arr , l 1 , r ) v_1 = \textit{func}(\textit{arr}, l_1, r) v1=func(arr,l1,r) v 2 = func ( arr , l 2 , r ) v_2 = \textit{func}(\textit{arr}, l_2, r) v2=func(arr,l2,r),则一定有 v 1 ≤ v 2 v_1 \le v_2 v1v2,理由如下。

对于 c = a & b c = a ~\&~ b c=a & b,考虑二进制表示的每一位,只有当 a a a b b b 在同一位的值都是 1 1 1 时, c c c 在该位的值才是 1 1 1,否则 c c c 在该位的值是 0 0 0,因此 c ≤ a c \le a ca c ≤ b c \le b cb。根据 func \textit{func} func 的定义有 v 1 = v 2 & ( arr [ l 1 ] & arr [ l 1 + 1 ] & … & arr [ l 2 − 1 ] ) v_1 = v_2 ~\&~ (\textit{arr}[l_1] ~\&~ \textit{arr}[l_1 + 1] ~\&~ \ldots ~\&~ \textit{arr}[l_2 - 1]) v1=v2 & (arr[l1] & arr[l1+1] &  & arr[l21]),利用按位与运算的性质可得 v 1 ≤ v 2 v_1 \le v_2 v1v2

因此,当子数组的右侧端点固定时,当左侧端点向左移动时函数值不变或减少,当左侧端点向右移动时函数值不变或增加。当左侧端点向左移动时,函数值的二进制表示的每一位只可能不变或从 1 1 1 变成 0 0 0,不可能从 0 0 0 变成 1 1 1,因此当子数组的右侧端点 r r r 固定时,不同的函数值个数不超过 O ( log ⁡ arr [ r ] ) O(\log \textit{arr}[r]) O(logarr[r])

m m m 表示数组 arr \textit{arr} arr 的最大值。利用上述结论,将数组 arr \textit{arr} arr 中的每个元素作为子数组的右侧端点时只需要考虑 O ( log ⁡ m ) O(\log m) O(logm) 个不同的函数值,不需要考虑 O ( n ) O(n) O(n) 个不同的函数值,可以将时间复杂度从 O ( n 2 ) O(n^2) O(n2) 降低到 O ( n log ⁡ m ) O(n \log m) O(nlogm)

具体做法是,将子数组的右侧端点初始化为 0 0 0,此时函数值为 arr [ 0 ] \textit{arr}[0] arr[0],计算 ∣ arr [ 0 ] − target ∣ \big| \textit{arr}[0] - \textit{target} \big| arr[0]target ,作为函数值与目标值的最小差值。对于 i i i 1 1 1 n − 1 n - 1 n1,将 i i i 作为子数组的右侧端点,当前轮的函数值包括上一轮的每个函数值分别与 arr [ i ] \textit{arr}[i] arr[i] 的按位与运算结果,以及 arr [ i ] \textit{arr}[i] arr[i],计算当前轮的每个函数值与目标值的差的绝对值,更新最小差值。

实现方面,区分上一轮的函数值和当前轮的函数值的做法有多种,可以创建两个列表分别存储上一轮的函数值和当前轮的函数值,也可以使用队列存储函数值。使用队列的做法如下。

  1. 当遍历到 arr [ i ] \textit{arr}[i] arr[i] 时,队列中的元素为上一轮的所有函数值,记录此时队列的大小 size \textit{size} size

  2. size \textit{size} size 个元素出队列,将每个出队列的元素和 arr [ i ] \textit{arr}[i] arr[i] 做按位与运算得到当前轮的函数值,将当前轮的函数值入队列。

  3. 最后将 arr [ i ] \textit{arr}[i] arr[i] 入队列,表示 l = r = i l = r = i l=r=i 的情况下对应的函数值。

将当前轮的函数值入队列时需要排除重复元素。由于遍历函数值的顺序具有单调性,因此相等的函数值在遍历顺序中一定相邻,每次将函数值入队列时判断当前函数值与上一个入队列的函数值是否相等,即可排除重重复元素。

代码

class Solution {public int closestToTarget(int[] arr, int target) {int minDiff = Math.abs(arr[0] - target);Queue<Integer> queue = new ArrayDeque<Integer>();queue.offer(arr[0]);int length = arr.length;for (int i = 1; i < length; i++) {int num = arr[i];int size = queue.size();int lastVal = -1;for (int j = 0; j < size; j++) {int prevVal = queue.poll();int currVal = prevVal & num;if (currVal != lastVal) {minDiff = Math.min(minDiff, Math.abs(currVal - target));queue.offer(currVal);lastVal = currVal;}}if (num != lastVal) {minDiff = Math.min(minDiff, Math.abs(num - target));queue.offer(num);}}return minDiff;}
}

复杂度分析

  • 时间复杂度: O ( n log ⁡ m ) O(n \log m) O(nlogm),其中 n n n 是数组 arr \textit{arr} arr 的长度, m m m 是数组 arr \textit{arr} arr 的最大值。遍历数组的过程中,对于每个元素需要 O ( log ⁡ m ) O(\log m) O(logm) 的时间计算以当前元素作为结尾的所有函数值,因此时间复杂度是 O ( n log ⁡ m ) O(n \log m) O(nlogm)

  • 空间复杂度: O ( log ⁡ m ) O(\log m) O(logm),其中 m m m 是数组 arr \textit{arr} arr 的最大值。空间复杂度主要取决于队列,队列中的元素个数不超过 O ( log ⁡ m ) O(\log m) O(logm)

http://www.xdnf.cn/news/472303.html

相关文章:

  • 新手入门系列-springboot项目初体验
  • C盘清理秘籍:快速提升系统性能
  • Python 调试扩展版本兼容问题解决纪实
  • 在自动化脚本中使用找色实现精确定位目标区域
  • docker 学习记录
  • uniapp x
  • 软件安全测试报告:检测商业软件安全性,发现潜在风险点?
  • 修复“ImportError: DLL load failed while importing lib: 找不到指定的程序”笔记
  • MySQL 误删除数据恢复全攻略:基于 Binlog 的实战指南
  • 深度学习入门:深度学习(完结)
  • 张量与Python标量:核心区别与计算图断开解析
  • 白平衡模块中普朗克曲线拟合硬件实现的猜想
  • ElfBoard技术实战|ELF 2开发板本地部署DeepSeek大模型的完整指南
  • MyBatis 的分页插件 c
  • 国产芯片LH001-91为什么可以代替TI的ADS1291?
  • 观QFramework框架底层逻辑有感
  • 丝杆升降机限位失灵深度剖析:从故障机理到智能监测方案
  • 硬件创新新纪元:从算力怪兽到便携革命,2025 年如何重新定义计算体验
  • unordered_set和unordered_map
  • 详细解释api
  • 不同进制的数据展示(十进制、十六进制、编码方式)
  • 理解 Viewport:让网页在手机端正确显示的秘诀
  • 星形测试卡:射线摄影获取焦点星卡射线照片的工具
  • win11安装Joplin Server私有化部署(docker)
  • 【应急响应工具教程】Windows日志快速分析工具——Chainsaw
  • 数智管理学(九)
  • MySQL 8.0 OCP 1Z0-908 题目解析(4)
  • Process exited with an error: 1 (Exit value: 1) 问题处理
  • Element Plus 取消el-form-item点击触发组件,改为原生表单控件
  • Seata源码—3.全局事务注解扫描器的初始化一