leetcode每日一题:最大或值

题目
给你一个下标从 0 开始长度为 n 的整数数组 nums 和一个整数 k 。每一次操作中,你可以选择一个数并将它乘 2 。
你最多可以进行 k 次操作,请你返回 nums[0] | nums[1] | ... | nums[n - 1] 的最大值。
a | b 表示两个整数 a 和 b 的 按位或 运算。
示例 1:
输入:nums = [12,9], k = 1
输出:30
解释:如果我们对下标为 1 的元素进行操作,新的数组为 [12,18] 。此时得到最优答案为 12 和 18 的按位或运算的结果,也就是 30 。
示例 2:
输入:nums = [8,1,2], k = 2
输出:35
解释:如果我们对下标 0 处的元素进行操作,得到新数组 [32,1,2] 。此时得到最优答案为 32|1|2 = 35 。
提示:
1 <= nums.length <= 1051 <= nums[i] <= 1091 <= k <= 15
思路
考虑了挺久,看到方法最后的返回值是long,才反应过来。本题其实有个隐含的条件没有说,就是选择1个数乘以2之后,是可以超出int范围的。有了这个条件之后,就豁然开朗了。那要让最后的或值最大,肯定要把这k次操作用在同一个数字上。因为每次乘以2的操作,相当于二进制数的左移1位,选择同一个数左移,才能把最高的1移动到尽量靠左,即更加高位的位置,让整体数值最大。
接下来就是在遍历的过程中,如何快速计算。对于每个数,我们要计算这个数左移k位,跟剩余其他数值的或值。为了避免重复计算,我们定义2个数组prefix[]和suffix[],prefix[i]代表nums[0, i-1]的或值,suffix[i]代表nums[i+1, n-1]的或值。可以运用类似前缀和的方法,预先计算好这2个数组,然后再遍历nums计算最大或值。这里有一个小技巧,对prefix[]的计算,由于是从前往后遍历的,可以跟nums的遍历放在同一个for循环中,这样可以减少一次遍历,虽然时间复杂度不变,不过也可以节省一些执行时间。
图解

代码

public long maximumOr(int[] nums, int k) {
int n = nums.length;
// 后缀 or 结果
int[] suffix = new int[n];
for (int i = n - 1; i >= 1; i--) {
suffix[i-1] = suffix[i] | nums[i];
}
long ans = 0;
long prefix = 0;
for (int i = 0; i < n; i++) {
ans = Math.max(ans, prefix | ((long) nums[i] << k) | suffix[i]);
prefix |= (long) nums[i];
}
return ans;
}
优化
上述方法中,开了2个长度为n的数组prefix[]和suffix[],我们想办法优化。最直接可以想到的是,我们对nums所有的值先做1次or计算,得到orResult,然后在遍历到某个值num的时候,通过异或预算,去除掉这个num的影响,这样就获的了去除当前num,剩余所有值的或结果。
但是这样会存在一个问题:对于num的二进制表示中所有为1的位,异或运算后都变成了0,如果这1位其他数是有1的,那么就多去除了。所以,我们还需要计算一个值fixed,代表在这1位,至少存在2个数的二进制表示为1,那么无论结果选择对那个num进行左移,这1位固定为1,我们在异或计算后,再次或运算fixed,就可以得到真正的,去除当前num后,剩余数值的或值。
优化后代码

public long maximumOr(int[] nums, int k) {
long orResult = 0;
// 如果多个数值在某1位是1,那么无论这个数是否做位移,or的结果这1位一定是1
long fixed = 0;
for (int num : nums) {
fixed |= orResult & num;
orResult |= num;
}
// 遍历的时候,通过 ^num 把这一位的数值排除掉,同时 |fixed 避免多排除的影响
long ans = 0;
for (int num : nums) {
ans = Math.max(ans, (orResult ^ num) | fixed | ((long)num<<k));
}
return ans;
}
耗时

leetcode每日一题:最大或值的更多相关文章
- 【python】Leetcode每日一题-逆波兰表达式求值
[python]Leetcode每日一题-逆波兰表达式求值 [题目描述] 根据 逆波兰表示法,求表达式的值. 有效的算符包括 +.-.*./ .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 说 ...
- 【JavaScript】Leetcode每日一题-在D天内送包裹的能力
[JavaScript]Leetcode每日一题-在D天内送包裹的能力 [题目描述] 传送带上的包裹必须在 D 天内从一个港口运送到另一个港口. 传送带上的第 i 个包裹的重量为 weights[i] ...
- 【JavaScript】Leetcode每日一题-青蛙过河
[JavaScript]Leetcode每日一题-青蛙过河 [题目描述] 一只青蛙想要过河. 假定河流被等分为若干个单元格,并且在每一个单元格内都有可能放有一块石子(也有可能没有). 青蛙可以跳上石子 ...
- 【JavaScript】Leetcode每日一题-平方数之和
[JavaScript]Leetcode每日一题-平方数之和 [题目描述] 给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a2 + b2 = c . 示例1: 输入:c = 5 ...
- 【JavaScript】Leetcode每日一题-二叉搜索树的范围和
[JavaScript]Leetcode每日一题-二叉搜索树的范围和 [题目描述] 给定二叉搜索树的根结点 root,返回值位于范围 [low, high] 之间的所有结点的值的和. 示例1: 输入: ...
- 【JavaScript】Leetcode每日一题-递增顺序搜索树
[JavaScript]Leetcode每日一题-递增顺序搜索树 [题目描述] 给你一棵二叉搜索树,请你 按中序遍历 将其重新排列为一棵递增顺序搜索树,使树中最左边的节点成为树的根节点,并且每个节点没 ...
- 【python】Leetcode每日一题-寻找旋转排序数组中的最小元素
[python]Leetcode每日一题-寻找旋转排序数组中的最小元素 [题目描述] 已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组.例如,原数组nums ...
- 【JavaScript】Leetcode每日一题-矩形区域不超过K的最大值和
[JavaScript]Leetcode每日一题-矩形区域不超过K的最大值和 [题目描述] 给你一个 m x n 的矩阵 matrix 和一个整数 k ,找出并返回矩阵内部矩形区域的不超过 k 的最大 ...
- 【JavaScript】【KMP】Leetcode每日一题-实现strStr()
[JavaScript]Leetcode每日一题-实现strStr() [题目描述] 实现 strStr() 函数. 给你两个字符串 haystack 和 needle ,请你在 haystack 字 ...
- 【JavaScript】Leetcode每日一题-移除元素
[JavaScript]Leetcode每日一题-移除元素 [题目描述] 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度. 不要使用 ...
随机推荐
- 微服务实战系列(二)-注册中心Springcloud Eureka客户端-copy
1. 场景描述 前几天介绍了下springcloud的Eureka注册中心(springcloud-注册中心快速构建),今天结合springboot-web介绍下eureka客户端服务注册. 2. 解 ...
- Nacos、Apollo、SpringCloud Config微服务配置中心对比
1为什么需要配置中心 配置实时生效: 传统的静态配置方式要想修改某个配置只能修改之后重新发布应用,要实现动态性,可以选择使用数据库,通过定时轮询访问数据库来感知配置的变化.轮询频率低感知配置变化的延时 ...
- java多线程---总结(1)
线程创建.start.run 一.创建线程方式 java创建线程的方式,主要有三种:类Thread.接口Runnable.接口Callable. 1.Thread和Runnable进行比较 他们之间的 ...
- Go语言【Gin框架】:JSON、AsciiJSON、PureJSON和SecureJSON的区别
在Go语言中,JSON.AsciiJSON.PureJSON 和 SecureJSON 是Gin框架用于发送JSON响应的方法. 1. c.JSON 功能:将提供的数据序列化为标准的JSON格式,并将 ...
- day04-数组
Java数组 [ 任务列表 ] 1.数组 2.二维数组 3.其他 --------------------------------------------------------- 1.数组 数组:存 ...
- Q:windows server2019由于没有远程桌面授权服务器可以提供许可证,远程回话连接已断开
由于没有远程桌面授权服务器可以提供许可证,远程回话连接已断开,请跟服务管理员联系 原因是服务器安装了远程桌面服务RemoteApp,这个是需要授权的.但是微软官方给予了120天免授权使用,超过120天 ...
- QT5笔记: 23. 标准对话框
文件对话框: QString fileName = QFileDialog::getOpenFileName(this, "打开一个文件", path, "文本(*.tx ...
- 个人文件转移工具-来自某位大神的C盘清理神器
软件名称:个人文件转移工具 软件功能:文件转移 支持平台:Windows 软件简介:一款文件转移工具,也可用作C盘瘦身. 软件特点: ◉ "个人文件转移工具"可以把"我的 ...
- Ansible - [10] Vault(加密&解密)
加密文件 Ansible 有时需要访问一些敏感数据,如密码.Key等 使用ansible-vault可以加密和解密数据 # 创建测试文件 [root@control ansible]# echo 12 ...
- Kafka - [02] Kafka单机版部署
Kafka是一个分布式的流处理平台. kafka主要是作为一个分布式的.可分区的.具有副本数的日志服务系性.高容错性.访问速度快.分布式等特性:具有高水平扩展 主要应用场景是:日志收集系统和分布式发布 ...