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

力扣第 411 场周赛题解

3258. 统计满足 K 约束的子字符串数量 I

给你一个 二进制 字符串 s 和一个整数 k

如果一个 二进制字符串 满足以下任一条件,则认为该字符串满足 k 约束

  • 字符串中 0 的数量最多为 k
  • 字符串中 1 的数量最多为 k

返回一个整数,表示 s 的所有满足 k 约束 

子字符串

的数量。

示例 1:

输入:s = "10101", k = 1

输出:12

解释:

s 的所有子字符串中,除了 "1010""10101" 和 "0101" 外,其余子字符串都满足 k 约束。

示例 2:

输入:s = "1010101", k = 2

输出:25

解释:

s 的所有子字符串中,除了长度大于 5 的子字符串外,其余子字符串都满足 k 约束。

示例 3:

输入:s = "11111", k = 1

输出:15

解释:

s 的所有子字符串都满足 k 约束。

提示:

  • 1 <= s.length <= 50
  • 1 <= k <= s.length
  • s[i] 是 '0' 或 '1'

题目说满足任意条件即可成立,也就是说两个条件同时都不满足时结果不成立.看到题目数据范围,我们可以采用暴力枚举每一种情况,时间复杂度O(n^2),可以过.

class Solution {
public:int countKConstraintSubstrings(string s, int k) {int count = 0;for (int i = 0; i < s.size(); i++) {int zeroCount = 0;int oneCount = 0;for (int j = i; j < s.size(); j++) {if (s[j] == '0') zeroCount++;if (s[j] == '1') oneCount++;if (zeroCount <= k || oneCount <= k) {count++;}}}return count;}
};

但是我们要想优化,可以考虑以下标0,1,2,3.....为右端点的子串个数统计出来,例如10101,以下标0为右端点的子串为1;以下标1为右端点的子串为0,10;以下标2为右端点的子串为101,01,1......以此类推,然后把这些所有子串个数都加起来就是答案,但是,例如1010101,k=2,枚举到下标为5,即101010,就不符合要求了,但可以把子串缩小,例如01010,就符合要求了,不难发现如果这个长度为5的子串符合要求,那么长度更短的子串也符合要求,所以比如说右端点为0时,左端点最远为第一个0的位置,左端点L=1,右端点R=5,那么从[L,R],[L+1,R].....到[R,R]都是符合的,一共R-L+1个数,把这些数的个数加到答案里面就可以了,同时,当右端点增大时,比如增大到末尾的1时,就不符合要求了,所以要将左端点增大,所以可以推出当右端点增大时,左端点要么不变,要么增大,符合滑动窗口的思想,时间复杂度O(n),n为字符串长度,L只会增加,不会减少,所以为O(n).

class Solution {
public:int countKConstraintSubstrings(string s, int k) {int cnt[2],l=0,ans=0;for(int i=0;i<s.size();i++){cnt[s[i]%2]++;while(cnt[0]>k&&cnt[1]>k)cnt[s[l++]%2]--;ans+=i-l+1;}return ans;}
};

3259. 超级饮料的最大强化能量

来自未来的体育科学家给你两个整数数组 energyDrinkA 和 energyDrinkB,数组长度都等于 n。这两个数组分别代表 A、B 两种不同能量饮料每小时所能提供的强化能量。

你需要每小时饮用一种能量饮料来 最大化 你的总强化能量。然而,如果从一种能量饮料切换到另一种,你需要等待一小时来梳理身体的能量体系(在那个小时里你将不会获得任何强化能量)。

返回在接下来的 n 小时内你能获得的 最大 总强化能量。

注意 你可以选择从饮用任意一种能量饮料开始。

示例 1:

输入:energyDrinkA = [1,3,1], energyDrinkB = [3,1,1]

输出:5

解释:

要想获得 5 点强化能量,需要选择只饮用能量饮料 A(或者只饮用 B)。

示例 2:

输入:energyDrinkA = [4,1,1], energyDrinkB = [1,1,3]

输出:7

解释:

  • 第一个小时饮用能量饮料 A。
  • 切换到能量饮料 B ,在第二个小时无法获得强化能量。
  • 第三个小时饮用能量饮料 B ,并获得强化能量。

提示:

  • n == energyDrinkA.length == energyDrinkB.length
  • 3 <= n <= 105
  • 1 <= energyDrinkA[i], energyDrinkB[i] <= 105

例如,[1,3,1]和 [3,1,1],题目中说每小时只能饮用一种能量饮料,且相邻的下标不能连续选择不同数组中的数,所以如果选定一个数组,可以连着选,但是选不同数组,只能跳着选.同时,题目保证所有数为正数,所以最后一个数一定要选(比如第一个数组,只选3和既选3又选1,肯定后者更优)  (因为题目给了两个数组a,b,从a数组选若干数,从b数组选若干数,相当于从两个数组中各选了一个子序列,所以对于子序列题目,可以考虑最后一个数是怎么选的),所以选了最后一个数之后,接下来分两种情况,要么选同一个数组中的倒数第二个数,要么跳着选另一个数组的倒数第三个数(不能隔两个数选下一个,因为结果不优),所以这道题本质就是选或不选的题,比如选完第一个数组的最后一个1之后,接下来选第一个数组中的3,转化为从[1,3],[3,1]的选择情况;接下来选第二个数组中的3,就转化为没有数字选了.所以需要两个变量,一个是用i表示从下标0到下标i的数,第二个是用j表示从第i个位置选的数是属于a数组还是b数组(j=0表示从a数组选,也就是选了ai;j=1表示从b数组选,也就是选了bi).用dfs(i,j)表示从下标[0,i]中选,且下标i选的数为a[i](j==0),或者b[i](j==1),所以就是dfs(i-1,j)和dfs(i-2,1-j),二者取最大值,定义数组c,将数组a和b放进c中(下标0就是a,1就是b),还要考虑如果i<0,结果就越界了,所以直接返回0,所以dfs(i,j)=max(dfs(i-1,j),dfs(i-2,1-j))+c[j][i].结果返回的就是max(dfs(n-1,0),dfs(n-1,1)).考虑到整个递归过程中有大量重复递归调用(递归入参相同),由于递归函数没有副作用,同样的入参无论计算多少次,算出来的结果都是一样的,因此可以用记忆化搜索来优化.(python直接加@cache).也可以把记忆化搜索翻译成递推,当i=0时,递归到-2,i的范围是从-2到n-1,有n+2个数,j就是0,1.把dfs(-2,j)翻译成f[0][j],dfs(-1,j)翻译成f[1][j],dfs(i,j)=max(dfs(i-1,j),dfs(i-2,1-j))+c[j][i]翻译成f[i+2][j]=max(f[i+1][j],f[i][1-j])+c[j][i].(如果把数组c中的i加上2后,当i=n-1时,就越界了,所以不能加2,还有就是仅仅是在f数组前面插入状态,没在c数组前插入状态,所以不改变c数组),答案为 max(f[n+1][0],f[n+1][1]).

class Solution {
public:long long maxEnergyBoost(vector<int>& a, vector<int>& b) {int n = a.size();vector<array<long long,2>>f(n + 2);for (int i = 0; i < n; i++) {f[i+2][0]=max(f[i+1][0],f[i][1])+a[i];f[i+2][1]=max(f[i+1][1],f[i][0])+b[i];}return max(f[n+1][0],f[n+1][1]);}
};

3260. 找出最大的 N 位 K 回文数

给你两个 正整数 n 和 k

如果整数 x 满足以下全部条件,则该整数是一个 k 回文数

  • x 是一个 回文数。
  • x 可以被 k 整除。

以字符串形式返回 最大的  n 位 k 回文数

注意,该整数 不 含前导零。

示例 1:

输入: n = 3, k = 5

输出: "595"

解释:

595 是最大的 3 位 k 回文数。

示例 2:

输入: n = 1, k = 4

输出: "8"

解释:

1 位 k 回文数只有 4 和 8。

示例 3:

输入: n = 5, k = 6

输出: "89898"

提示:

  • 1 <= n <= 105
  • 1 <= k <= 9

在i位置填了数字a,也同时在n-1-i位置填了数字a,在生成答案之前,只需考虑回文数%k的结果,例如三位数,中间位置初始化为0,则有9种情况(题目说不含前导零):101,202,.....909,接下来考虑每一个数中间填0~9又有10种情况,仅仅是三位数就有这么多种情况,如何减少考虑的数字的数量?这里有一个数学公式:(a+b)%k=(a%k+b%k)%k------取模恒等式,就是不用把整个数字生成出来去看%k的结果,可以在生成数字过程中直接%k.用i表示当前填到数字的哪一位,用j表示填的数字%k的结果.一开始为(0,0),当i=m时表示所有数都填好了(m=n/2上取整,比如一个6位数,从右到左i依次取0,1...5,当i=2时,还没填好,当i=3时,所有数字都填好了,比如一个5位数,i=2时继续填,i=3时填好了),即从起点(0,0)--->终点(m,0),m=n/2上取整.期间状态为从(1,(9*10的n-1次方+9)%k).....到(1,(1*10的n-1次方+1)%k),又可以递归到(i+1,....)...可以将题目考虑为图论问题,就是经过一些点最后到达终点,路径可以表示出填哪些数字,就是dfs暴搜加上vis数组记录访问过的结点.

class Solution {
public:
bool dfs(int i,int j,int n,int k,int m,vector<int>& pow10,string& ans,vector<vector<int>>&vis){if(i==m) return j==0;vis[i][j]=true;for (int d=9;d>=0;d--){ int j2;if(n%2&&i==m-1){ j2=(j+d*pow10[i])%k;}else{j2=(j+d*(pow10[i]+pow10[n-1-i]))%k;}if(!vis[i+1][j2]&&dfs(i+1,j2,n,k,m,pow10,ans,vis)){ans[i]=ans[n-1-i]='0'+d;return true;}}return false;
}
string largestPalindrome(int n,int k){vector<int>pow10(n);pow10[0]=1;for(int i=1;i<n;i++){pow10[i]=pow10[i-1]*10%k;}string ans(n,0);int m=(n+1)/2;vector<vector<int>>vis(m+1,vector<int>(k));dfs(0,0,n,k,m,pow10,ans,vis);return ans;}
};

3261. 统计满足 K 约束的子字符串数量 II

给你一个 二进制 字符串 s 和一个整数 k

另给你一个二维整数数组 queries ,其中 queries[i] = [li, ri] 。

如果一个 二进制字符串 满足以下任一条件,则认为该字符串满足 k 约束

  • 字符串中 0 的数量最多为 k
  • 字符串中 1 的数量最多为 k

返回一个整数数组 answer ,其中 answer[i] 表示 s[li..ri] 中满足 k 约束的子字符串的数量。

示例 1:

输入:s = "0001111", k = 2, queries = [[0,6]]

输出:[26]

解释:

对于查询 [0, 6], s[0..6] = "0001111" 的所有子字符串中,除 s[0..5] = "000111" 和 s[0..6] = "0001111" 外,其余子字符串都满足 k 约束。

示例 2:

输入:s = "010101", k = 1, queries = [[0,5],[1,4],[2,3]]

输出:[15,9,3]

解释:

s 的所有子字符串中,长度大于 3 的子字符串都不满足 k 约束。

提示:

  • 1 <= s.length <= 105
  • s[i] 是 '0' 或 '1'
  • 1 <= k <= s.length
  • 1 <= queries.length <= 105
  • queries[i] == [li, ri]
  • 0 <= li <= ri < s.length
  • 所有查询互不相同

此题和第一题不同在于本题是要求子串中有多少个合法的子串,用Left[i]表示以i为右端点的子串通过滑动窗口求出的Left的位置,例如,一子串范围为[L,R],如果这个范围里所有的Left[i]都在L的左边,那么这里面所有子串都符合要求,长度为m的子串有1+2+3+...+m=(m+1)*m/2个子串,如果某个子串中有指向外面的,也有指向里面的,如果右端点指向的Left[i]在询问的区间内,那么直接可以把r-l+1加到答案里面,不难发现,每个位置都对应一个r-l+1,可以理解为关于r-l+1的子数组的和,就可以用前缀和优化.所以该题就分为两种情况:找一个位置,在这个位置左边所有子串全部都是合法的,直接用等差数列之和,在这个位置右边的子串,用前缀和算出来,所以回答每次询问,就取决于能不能快速找到分界位置,因为滑动窗口的左端点是不断向右移动的,所以这个Left数组是一个有序数组,可以在这个有序数组中二分找到大于等于L第一个位置作为分界位置.

class Solution {
public:vector<long long> countKConstraintSubstrings(string s, int k, vector<vector<int>>& queries) {int n=s.length(),m=queries.size();vector<int>left(n);vector<long long>sum(n+1);int cnt[2]{},l=0;for (int i=0;i<n;i++){cnt[s[i]%2]++;while(cnt[0]>k&&cnt[1]>k){cnt[s[l++]%2]--;}left[i]=l;// 计算 i-left[i]+1 的前缀和sum[i+1]=sum[i]+i-l+1;}vector<long long>ans(m);for (int i=0;i<m;i++){int l=queries[i][0],r=queries[i][1];int j=lower_bound(left.begin()+l,left.begin()+r+1,l)-left.begin();ans[i]=sum[r+1]-sum[j]+(long long)(j-l+1)*(j-l)/2;}return ans;}
};

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 西安旅游系统--论文pf
  • 每日快讯 | 京东健康:2024年上半年营收283亿元
  • vue+fastadmin跨域请求问题
  • 【Docker】宿主机上装个ES和使用docker装个ES有啥不一样
  • 【gitlab】gitlab-ce:17.3.0-ce.0 之2:配置
  • Windows 上使用 OpenSSL 生成一个 10 年有效期的自签名 PFX 证书
  • Spring Boot 3.3 【五】Spring Boot 整合JPA-原生SQL支持
  • 萝卜快跑和端到端的自动驾驶(1)
  • mysql 之 explain
  • c语言基础-------数组元素的指针
  • 2024新型数字政府综合解决方案(七)
  • Apache Doris 中Compaction问题分析和典型案例
  • drawio的问题
  • 24 初入python
  • ECMAScript性能优化技巧与陷阱
  • 自己简单写的 事件订阅机制
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • css系列之关于字体的事
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • in typeof instanceof ===这些运算符有什么作用
  • iOS仿今日头条、壁纸应用、筛选分类、三方微博、颜色填充等源码
  • laravel5.5 视图共享数据
  • oldjun 检测网站的经验
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 面试题:给你个id,去拿到name,多叉树遍历
  • 扑朔迷离的属性和特性【彻底弄清】
  • 前端存储 - localStorage
  • 如何实现 font-size 的响应式
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • 我的zsh配置, 2019最新方案
  • 一份游戏开发学习路线
  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • const的用法,特别是用在函数前面与后面的区别
  • 湖北分布式智能数据采集方法有哪些?
  • ​​​​​​​STM32通过SPI硬件读写W25Q64
  • ​14:00面试,14:06就出来了,问的问题有点变态。。。
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​直流电和交流电有什么区别为什么这个时候又要变成直流电呢?交流转换到直流(整流器)直流变交流(逆变器)​
  • ###STL(标准模板库)
  • (06)金属布线——为半导体注入生命的连接
  • (24)(24.1) FPV和仿真的机载OSD(三)
  • (7)svelte 教程: Props(属性)
  • (DFS + 剪枝)【洛谷P1731】 [NOI1999] 生日蛋糕
  • (Java实习生)每日10道面试题打卡——JavaWeb篇
  • (poj1.2.1)1970(筛选法模拟)
  • (STM32笔记)九、RCC时钟树与时钟 第一部分
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (二十五)admin-boot项目之集成消息队列Rabbitmq
  • (五)MySQL的备份及恢复
  • (一) 初入MySQL 【认识和部署】
  • (转)IOS中获取各种文件的目录路径的方法
  • (转)PlayerPrefs在Windows下存到哪里去了?
  • (转)大道至简,职场上做人做事做管理
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)