leetcode134双周赛 子数组按位与值为 K 的数目「动态规划」「位运算」

3209. 子数组按位与值为 K 的数目

题目描述

给你一个整数数组 nums 和一个整数 k ,请你返回 nums 中有多少个子数组满足:子数组中所有元素按位 AND 的结果为 k

思路1:动态规划

打力扣打PTSD了,看什么题都是DP

状态: d p [ i ] [ j ] dp[i][j] dp[i][j]表示以 n u m [ i ] num[i] num[i]结尾,二进制第 j j j位连续是1的最长长度

状态转移:

  • 如果 n u m s [ i ] nums[i] nums[i]的第 j j j是1,则 d p [ i ] [ j ] = d p [ i − 1 ] [ j ] + 1 dp[i][j] = dp[i - 1][j] + 1 dp[i][j]=dp[i1][j]+1
  • 否则, d p [ i ] [ j ] = 0 dp[i][j] = 0 dp[i][j]=0

有了状态以后,怎么计算答案?

我们可以枚举子数组的右边界 i i i ,然后想办法去计算左边界的一个上界和下界

  • 如果 k k k的第 j j j位是1,根据&运算的性质,则满足条件的子数组的每个数的第 j j j位都应该是1。所以我们对k的每一个是1的位,求对应 d p [ i ] [ j ] dp[i][j] dp[i][j]的最小值,计作minx,求最小值的原因是,我们要求出满足这个子区间所有k是1的位都是1的最短长度,这是上界,不能再往前找了,因为只要再往前一位,一定存在一位本该是1的位置&上了0,变成了0,使得区间&起来不是k
  • 如果k的第 j j j位是0,根据&运算的性质,则满足条件的子数组的第 j j j位应该至少有一个0,所以我们对k的每一个是0的位,求对应 d p [ i ] [ j ] dp[i][j] dp[i][j]的最大值,计作maxn,求最大值的原因是, d p [ i ] [ j ] dp[i][j] dp[i][j]代表第 n u m s [ i ] nums[i] nums[i]的第 j j j位往前连续的1的最长长度,我们现在要保证有一个0,则往前的第一个0是位于往前 d p [ i ] [ j ] + 1 dp[i][j]+1 dp[i][j]+1的位置,这是下界,是可以再往前找的,因为前面不管是什么,我们是0的位置&起来都是0
  • 所以答案就是 m a x ( 0 , m i n x − m a x n ) max(0, minx - maxn) max(0,minxmaxn)

对于每个右边界 i i i,我们都算出 m a x n maxn maxn m i n x minx minx,求个 ∑ m a x ( 0 , m i n x − m a i n ) \sum{max(0, minx-main)} max(0,minxmain)就行

class Solution {
public:long long countSubarrays(vector<int>& nums, int k) {int n = nums.size();vector<vector<int>>dp(n + 1, vector<int>(32));long long ans = 0;for(int i = 1; i <= nums.size(); ++i){for(int j = 0; j < 32; ++j){if((nums[i - 1]>>j) & 1)dp[i][j] = dp[i - 1][j] + 1;else dp[i][j] = 0;}int minx = i, maxn = 0;for(int j = 0; j < 32; ++j){if((k>>j)&1)minx = min(minx, dp[i][j]);else maxn = max(maxn, dp[i][j]);}cout<< minx << " " << maxn << endl;ans += max(0, minx - maxn);}return ans;}
};

思路2:位运算性质+二分

考虑一个简单问题,给定一个数组,如何求所有(子区间 n u m [ i ] num[i] num[i] n u m [ j ] num[j] num[j]进行与操作后起来)的结果

我们可以对数组进行如下操作:

  • 我们搞一个 n e w _ n u m new\_num new_num数组,初始 n e w _ n u m [ i ] = n u m [ i ] new\_num[i]=num[i] new_num[i]=num[i]
  • 然后 i i i从1开始遍历到n, j j j i − 1 i-1 i1遍历到1,每次都把 n e w n u m [ i ] new_num[i] newnum[i]与前面所有的 n u m [ j ] num[j] num[j]进行与操作,即 n e w _ n u m [ j ] = n e w _ n u m [ j ] & n u m [ i ] new\_num[j] = new\_num[j]\& num[i] new_num[j]=new_num[j]&num[i]
  • 这样操作会使得每次遍历完 i i i,会使得 n e w _ n u m [ j ] new\_num[j] new_num[j]变成 n u m [ j ] & n u m [ j + 1 ] & . . . & n u m [ i ] num[j]\&num[j+1]\&...\&num[i] num[j]&num[j+1]&...&num[i]
  • 在这个过程中就可以得到所有的子区间数字相与的结果

但是如果仅仅是这样做,只会是标准的 O ( n 2 ) O(n^2) O(n2)复杂度,我们可以想办法优化一下

由于&操作,一定会让数字变小或者不变,所以我们在第二层枚举的时候,可以判断一下如果 n e w _ n u m [ j ] = = n e w _ n u m [ j ] & n u m [ i ] new\_num[j]==new\_num[j]\&num[i] new_num[j]==new_num[j]&num[i],说明
n u m [ j ] & n u m [ j + 1 ] & . . . & n u m [ i − 1 ] = = n u m [ j ] & n u m [ j + 1 ] & . . . & n u m [ i − 1 ] & n u m [ i ] num[j]\&num[j+1]\&...\&num[i-1] == num[j]\&num[j+1]\&...\&num[i-1]\&num[i] num[j]&num[j+1]&...&num[i1]==num[j]&num[j+1]&...&num[i1]&num[i]
也就是说 & \& & n u m [ i ] num[i] num[i]不会使得 n e w _ n u m [ j ] new\_num[j] new_num[j]变小,那我们就可以停止第二层的循环了

我们可以将&操作看作集合的求交集操作,现在 n e w _ n u m [ j ] = = n e w _ n u m [ j ] & n u m [ i ] new\_num[j]==new\_num[j]\&num[i] new_num[j]==new_num[j]&num[i]说明 n e w _ n u m [ j ] new\_num[j] new_num[j]二进制是1的位置的集合一定是 n u m [ i ] num[i] num[i]二进制是1的位置的集合的子集,而因为 n e w _ n u m [ j − 1 ] = n e w _ n u m [ j ] & n u m [ j − 1 ] new\_num[j - 1] = new\_num[j] \& num[j-1] new_num[j1]=new_num[j]&num[j1],则 n e w _ n u m [ j − 1 ] < = n e w _ n u m [ j ] new\_num[j-1]<=new\_num[j] new_num[j1]<=new_num[j] n e w _ n u m [ j − 1 ] new\_num[j-1] new_num[j1]二进制是1的位置的集合一定是 n e w _ n u m [ j ] new\_num[j] new_num[j]二进制是1的位置的集合的子集,则集合的大小关系是 n e w _ n u m [ j − 1 ] ⊆ n e w _ n u m [ j ] ⊆ n u m [ i ] new\_num[j - 1]\subseteq{new\_num[j]}\subseteq{num[i]} new_num[j1]new_num[j]num[i]

那这样 n e w _ n u m [ j − 1 ] new\_num[j-1] new_num[j1]&上 n u m [ i ] num[i] num[i]也一定不变,当然,不是说只有 j − 1 j-1 j1不用&了,小于 j − 1 j-1 j1的也不用&了,证明同上

可以发现,如果想让数字变小,一定是至少有一位二进制位从1变成0,由于本题二进制下1最多30位,所以最坏的时间也就是 O ( n ∗ l o g ( m a x e l e m e n t ) ) O(n*log(max_element)) O(nlog(maxelement))

现在回到本题,本题求的是子区间&起来等于k的数量,我们只需要在循环 i i i的时候,统计一下 1 1 1 i i i n u m [ i ] = k num[i]=k num[i]=k的数量,求和就行, n u m [ i ] num[i] num[i]中数字都是连续出现且递增的,所以我们可以用二分来找

class Solution {
public:long long countSubarrays(vector<int>& nums, int k) {int n = nums.size();long long ans = 0;for(int i = 0; i < n; ++i){for(int j = i - 1; j >= 0; --j){if((nums[j] & nums[i]) == nums[j]){break;}nums[j] &= nums[i];}int l = lower_bound(nums.begin(), nums.begin() + i + 1, k) - nums.begin();int r = upper_bound(nums.begin(), nums.begin() + i + 1, k) - nums.begin();ans += r - l;}return ans;}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/869678.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c++ 宏和模板

&#xff08;1&#xff09;宏的应用 宏定义可以实现类似于函数的功能&#xff0c;但是它终归不是函数&#xff0c;而宏定义中括弧中的“参数”也不是真的参数&#xff0c;在宏展开的时候对 “参数” 进行的是一对一的替换。 assert() 断言 断言&#xff0c;是宏&#xff0c;…

【AMBA】AHB总线中的HTRANS、HSIZE、HBURST以及1K边界问题

HTRANS、HSIZE和HBURST共同决定下一次数据传输的地址。 HTRANS[1:0]定义传输类型 HTRANS[1:0]主机传输状态描述00IDLE空闲表示没有进行数据传输&#xff0c;默认状态。主设备虽然可能已经占用了总线&#xff0c;但是还没有开始传输数据。从设备需要返回OKAY响应01BUSY忙主设备…

springboot+vue项目实战2024第二集jwt

1.登陆注册校验token,jwt校验 <!--java-jwt--><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>4.4.0</version></dependency> <!--test--><dependency><groupId&…

在 Node.js 中,如何正确地使用 async/await 与 Promise 对象配合

在 Node.js 中&#xff0c;如何正确地使用 async/await 与 Promise 对象配合? 在Node.js中&#xff0c;async/await是ES2017引入的一种更简洁的处理异步操作的方式&#xff0c;它基于Promise来进行编写&#xff0c;使得异步代码看起来更像同步代码&#xff0c;易于理解和维护…

重塑视听盛宴:揭秘短剧系统开发背后的创意引擎与技术革新!

重塑视听盛宴&#xff0c;短剧系统的开发背后融合了强大的创意引擎与技术革新。这些创新不仅提升了观众的观剧体验&#xff0c;还极大地丰富了内容创作和分发的方式。 创意引擎 内容创新 1、多元化内容资源&#xff1a;短剧系统汇聚了全球各地的优质短剧资源&#xff0c;涵盖悬…

前端面试39(关于git)

针对前端开发者的Git面试题可以覆盖Git的基础概念、常用命令、工作流程、团队协作、以及解决冲突等方面。以下是一些具体的Git面试 Git基础知识 什么是Git&#xff1f; Git是一个分布式版本控制系统&#xff0c;用于跟踪计算机文件的更改&#xff0c;并协调多个人共同在一个项…

基于视觉的具身导航

基于视觉的具身导航 背景 什么是&#xff08;视觉的&#xff1f;&#xff09;具身导航 输入机器人观测的当前图像 o t o_t ot​和目标图像 o G o_G oG​&#xff0c;输出当前时间步的控制动作 u t u_t ut​&#xff0c;最终到达指定地点的算法流程。 通用的评价指标 性能指…

Git常见命令和用法

Git 文件状态 Git 文件 2 种状态: 未跟踪:新文件&#xff0c;从未被 Git 管理过已跟踪:Git 已经知道和管理的文件 常用命令 命令作用注意git -v查看 git 版本git init初始化 git 仓库初始化之后有工作区、暂存区(本地库)、版本库git add 文件标识暂存某个文件文件标识以终…

人工智能建立在对象存储上的真正原因

tl;dr: 在这篇文章中&#xff0c;我们将探讨 AI 工作负载依赖高性能对象存储的四个技术原因。 1. 对非结构化数据没有限制 在当前的机器学习范式中&#xff0c;性能和能力与计算成比例&#xff0c;计算实际上是数据集大小和模型大小的代理&#xff08;神经语言模型的缩放定律&a…

C#开发:下载node.js指定版本

一、打开官网 二、找到指定版本 三、选择程序包msi下载 四、验证下载是否成功 cmd输入&#xff1a; node -v npm -v

请跳至打印机属性的“Adobe PDF设置”页面,取消选择“仅停靠系统字体;不使用文档字体”

场景&#xff1a; 当使用adobe pdf打印时&#xff0c;出现如下提示“请跳至打印机属性的“Adobe PDF设置”页面&#xff0c;取消选择“仅停靠系统字体&#xff1b;不使用文档字体””&#xff0c;该如何解决。 描述 □“仅停靠系统字体&#xff1b;不使用文档字体” 复选本框…

【GameFramework扩展应用】6-1、接入热更新框架HybridCLR

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址QQ群:398291828大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 【GameFramework框架】系列教程目录: https://blog.csdn.net/q764424567/article/details/1…

基坑安全:自动化监测系统的革新力量

在日新月异的基坑工程领域&#xff0c;基坑安全自动化监测系统犹如一位守护者&#xff0c;以其独特的优势&#xff0c;为工程的安全与质量保驾护航。该系统集先进的测量仪器、计算机技术与现代传感技术于一体&#xff0c;对基坑的围护结构及周边环境进行全方位、高精度的实时监…

从零开始学量化~Ptrade使用教程(四)——股票普通买卖与回购业务

股票普通买卖 股票买入 通过选择委托方向实现股票的买入与卖出&#xff0c;可根据输入的价格自动查询可买数量。 用鼠标点击【买入】&#xff0c;如图所示&#xff1a; 输入股票代码并选中后&#xff0c;选择委托类型&#xff0c;若为限价类型&#xff0c;输入委托价格&#xf…

【漏洞复现】锐捷校园网自助服务系统 任意文件读取

声明&#xff1a;本文档或演示材料仅用于教育和教学目的。如果任何个人或组织利用本文档中的信息进行非法活动&#xff0c;将与本文档的作者或发布者无关。 一、漏洞描述 锐捷校园网自助服务系统是用于学校网络管理的一个平台&#xff0c;login_judge.jsf接口存在任意文件读取…

中职网络安全B模块渗透测试server2380

使用nmap扫描添加参数-sV Flag:2.4.38 添加参数-A不然扫不全 &#xff08;这两题可以直接加-sV -A&#xff09; Flag: 4.3.11-Ubuntu 根据nmap扫描发现系统为ubuntu系统&#xff0c;ubuntu操作系统在某些版本中默认包含一个名为"ubuntu"的用户帐户。这是为了方…

重生奇迹mu自带四重箭加穿透的弓

1.烈风射手 烈风射手是自带四重箭加穿透的弓之一。该职业的技能树中有一个叫做“四箭连发”的技能&#xff0c;可以让玩家在一次攻击中发射四支箭矢&#xff0c;每支箭矢都带有穿透效果。 2.影魅猎人 影魅猎人也是自带四重箭加穿透的弓之一。该职业的技能树中有一个叫做“穿…

案例分享:Qt modbusTcp调试工具(读写Byte、Int、DInt、Real、DReal)(当前v1.0.0)

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://blog.csdn.net/qq21497936/article/details/140313789 红胖子(红模仿)的博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片…

Backend - C# 操作PostgreSQL DB

目录 一、安装 Npgsql 插件 &#xff08;一&#xff09;作用 &#xff08;二&#xff09;操作 &#xff08;三&#xff09;注意 二、操作类 &#xff08;一&#xff09;操作类 1.NpgsqlConnection类 &#xff08;1&#xff09;作用 &#xff08;2&#xff09;引入 &a…

SpringSecurity中文文档(Servlet OAuth2)

OAuth2 Spring Security 提供了全面的 OAuth 2.0支持。 Overview Spring Security 的 OAuth 2.0支持包括两个主要特性集: OAuth2 Resource ServerOAuth2 Client OAuth2Login 是一个非常强大的 OAuth2Client 特性&#xff0c;值得在参考文档中单独列出。但是&#xff0c;它…