Leetcode - 周赛435

embedded/2025/2/13 9:32:33/

目录

  • 一、3442. 奇偶频次间的最大差值 I
  • 二、3443. K 次修改后的最大曼哈顿距离
  • 三、3444. 使数组包含目标值倍数的最少增量
  • 四、3445. 奇偶频次间的最大差值 II

一、3442. 奇偶频次间的最大差值 I

题目链接
在这里插入图片描述
本题使用数组统计字符串 s s s 中每个字符的出现次数,然后求出现次数为奇数的最大值和出现次数为偶数的最小值,将它们相减得到答案。

代码如下:

class Solution {public int maxDifference(String s) {int[] cnt = new int[26];for(char c : s.toCharArray()){cnt[c-'a']++;}int mx = 0, mn = Integer.MAX_VALUE;for(int x : cnt){if(x % 2 == 1){mx = Math.max(mx, x);}else if(x > 0){mn = Math.min(mn, x);}}return mx - mn;}
}

二、3443. K 次修改后的最大曼哈顿距离

题目链接
在这里插入图片描述
曼哈顿距离求两个坐标点 ( x i , y i ) (x_i,y_i) (xi,yi) ( x j , y j ) (x_j,y_j) (xj,yj) 的横坐标距离绝对值与纵坐标距离绝对值之和,即 ∣ x i − x j ∣ + ∣ y i − y j ∣ |x_i-x_j|+|y_i-y_j| xixj+yiyj,也就是说,可以将横纵坐标分开来计算:

  • 对于 x x x 轴来说(东西方向):比如说,此时向东移动了 a a a 步,向西移动了 b b b 步, a > b a > b a>b,肯定是将向西移动转换成向东移动,才会使得它距离原点距离越远。假设转换了 d d d 次,此时距离原点的距离就变成了 a + d − ( b − d ) = a − b + 2 ∗ d a + d - (b - d) = a - b + 2 * d a+d(bd)=ab+2d,如果 a < b a < b a<b,那么就是 b − a + 2 ∗ d b-a+2*d ba+2d,所以一合并变成了 a b s ( a − b ) + 2 ∗ d abs(a-b)+2*d abs(ab)+2d,这里的 d = m i n ( a , b , k ) d=min(a,b,k) d=min(a,b,k) k = k − d k = k- d k=kd
  • 对于 y y y 轴来说(南北方向)也是同理.

代码如下:

class Solution {public int maxDistance(String s, int k) {String str = "NSWE";int[] f = new int[4];int ans = 0;for(char c : s.toCharArray()){f[str.indexOf(c)]++;int left = k - Math.min(Math.min(f[0], f[1]), k);int res = get(f[0], f[1], k) + get(f[2], f[3], left);ans = Math.max(ans, res);}return ans;}int get(int x, int y, int k){int a = Math.max(x, y);int b = Math.min(x, y);int d = Math.min(b, k);return a - b + 2 * d;}
}
//也可以换一个角度思考,设当前位置为(x,y):
//由上一种方法可知,每一次修改都会使得曼哈都距离增加 2,最多不会超过 i + 1
class Solution {public int maxDistance(String s, int k) {int ans = 0;int x = 0, y = 0;for(int i = 0; i < s.length(); i++){char c = s.charAt(i);if(c == 'N') y++;else if(c == 'S') y--;else if(c == 'W') x--;else x++;ans = Math.max(ans, Math.min(Math.abs(x) + Math.abs(y) + 2 * k, i + 1));}return ans;}
}

三、3444. 使数组包含目标值倍数的最少增量

题目链接
在这里插入图片描述
对于 n u m s nums nums 数组中的任意一个元素来说,它可以成为 t a r g e t target target 数组中任意非空子集(从 t a r g e t target target 中任意选几个元素)的倍数,所以可以定义 d f s ( i , j ) dfs(i,j) dfs(i,j) [ 0 , i ] [0,i] [0,i] 满足集合 j j j 中所有倍数条件的最小操作次数(用集合 j = { x , y , z , . . . } j=\{x,y,z,...\} j={x,y,z,...} 表示 t a r g e t target target 数组中还剩下几个元素没有满足倍数条件)

如果从后往前遍历 n u m s nums nums 数组,对于 x = n u m s [ i ] x = nums[i] x=nums[i] 来说,它有选或不选两种情况:

  • 如果不选,即 x x x 不会进行递增操作,就不会变成集合 j j j 中任意元素的倍数,接下来问题变成前 i i i 个数满足集合 j j j 中所有元素倍数条件的最小操作次数,即 d f s ( i − 1 , j ) dfs(i-1,j) dfs(i1,j)
  • 如果选,即 x x x 会进行递增操作,就一定要变成集合 j j j 中任意非空子集的倍数,枚举集合 j j j 的所有非空子集 s u b sub sub,接下来问题变成前 i i i 个数满足集合 j − s u b j-sub jsub(即去除已选择的子集 s u b sub sub) 中所有元素倍数条件的最小操作次数,即 d f s ( i − 1 , j − s u b ) dfs(i-1,j-sub) dfs(i1,jsub)
  • d f s ( i , j ) = m i n ( d f s ( i − 1 , j ) , d f s ( i − 1 , j − s u b ) + o p e r a t i o n s ) dfs(i,j)=min(dfs(i-1,j),dfs(i-1,j-sub)+operations) dfs(i,j)=min(dfs(i1,j),dfs(i1,jsub)+operations) s u b ⊆ j sub\subseteq j subj o p e r a t i o n s operations operations 表示 n u m s [ i ] nums[i] nums[i] 变成 s u b sub sub 中所有元素的倍数的操作次数。

要计算 o p e r a t i o n s operations operations,需要先知道子集 s u b sub sub 中所有元素的最小公倍数,这里可以预处理出集合 j j j 所有子集的最小公倍数 l c m lcm lcm。这里介绍一个简单做法,定义 l c m s [ x ] lcms[x] lcms[x]:集合 x x x 中所有元素的最小公倍数。从小到大枚举集合 j j j 子集的大小,令 b i t = 1 < < i bit = 1<<i bit=1<<i,枚举所有大小小于 i i i 的子集 m a s k mask mask,可以得到 f [ b i t ∣ m a s k ] = l c m ( f [ m a s k ] , t a r g e t [ i ] ) f[bit | mask] = lcm(f[mask],target[i]) f[bitmask]=lcm(f[mask],target[i])

l = l c m s [ s u b ] l = lcms[sub] l=lcms[sub] o p e r a t i o n s = ( l − n u m s [ i ] % l ) % l operations=(l-nums[i]\%l)\%l operations=(lnums[i]%l)%l

代码如下:

class Solution {long gcd(long x , long y){return y == 0 ? x : gcd(y, x % y); }long lcm(long x, long y){return x * y / gcd(x, y);}public int minimumIncrements(int[] nums, int[] target) {int n = target.length;//预处理 lcmslong[] lcms = new long[1<<n];lcms[0] = 1;for(int i=0; i<n; i++){int bit = 1 << i;for(int j=0; j<bit; j++){lcms[bit|j] = lcm(target[i], lcms[j]);}}int m = nums.length;memo = new long[m][1<<n];for(long[] r : memo) Arrays.fill(r, -1);return (int)dfs(m-1, (1<<n)-1, nums, lcms);}long[][] memo;long dfs(int i, int j, int[] nums, long[] lcms){if(j == 0) return 0;if(i < 0) return Long.MAX_VALUE/2;if(memo[i][j] != -1) return memo[i][j];long res = dfs(i-1, j, nums, lcms);int sub = j;//枚举 j 的子集while(sub > 0){long l = lcms[sub];res = Math.min(res, dfs(i-1, j^sub, nums, lcms) + (l - nums[i] % l) % l);sub = (sub - 1) & j;}return memo[i][j] = res;}
}//递推写法
class Solution {long gcd(long x , long y){return y == 0 ? x : gcd(y, x % y); }long lcm(long x, long y){return x * y / gcd(x, y);}public int minimumIncrements(int[] nums, int[] target) {int n = nums.length;int m = target.length;long[] lcms = new long[1<<m];lcms[0] = 1;for(int i = 0; i < m; i++){int bit = 1 << i;for(int mask = 0; mask < bit; mask++){lcms[bit | mask] = lcm(target[i], lcms[mask]);}}long[][] f = new long[n+1][1<<m];Arrays.fill(f[0], Long.MAX_VALUE/2);for(int i = 0; i < n; i++){f[i][0] = 0;for(int j = 0; j < 1 << m; j++){f[i+1][j] = f[i][j];for(int sub = j; sub != 0; sub = (sub - 1) & j){long l = lcms[sub];f[i+1][j] = Math.min(f[i+1][j], f[i][j^sub] + (l - nums[i] % l) % l);}}}return (int)f[n][(1<<m)-1];}
}

四、3445. 奇偶频次间的最大差值 II

题目链接
在这里插入图片描述
题目中字符串 s s s 仅由数字 0 , 1 , 2 , 3 , 4 0,1,2,3,4 0,1,2,3,4 构成,所以可以枚举出现奇数次的字符 x x x 和出现偶数次的字符 y y y x ! = y x != y x!=y),求子串中两个字符出现的频次之差,就是求区间中字符 x x x y y y 的出现次数,然后相减。这个可以使用前缀和来进行计算:

假设数组 p r e x [ i + 1 ] pre_x[i+1] prex[i+1] 表示前 i i i 个元素中字符 x x x 的出现次数, p r e y [ i + 1 ] pre_y[i+1] prey[i+1] 表示前 i i i 个元素中字符 y y y 的出现次数,求区间 [ l , r ] [l,r] [l,r] x x x y y y 出现频次之差为 p r e x [ r + 1 ] − p r e x [ l ] − ( p r e y [ r + 1 ] − p r e y [ l ] ) pre_x[r+1]-pre_x[l]-(pre_y[r+1]-pre_y[l]) prex[r+1]prex[l](prey[r+1]prey[l]),把式子中 r + 1 r+1 r+1 放到一边, l l l 放到一边,得到 p r e x [ r + 1 ] − p r e y [ r + 1 ] − ( p r e x [ l ] − p r e y [ l ] ) pre_x[r+1]-pre_y[r+1]-(pre_x[l]-pre_y[l]) prex[r+1]prey[r+1](prex[l]prey[l]) ,此时发现,本题可以使用滑动窗口中的枚举右,维护左来做:

  • 本题要求子字符串的长度至少为 k k k,且子字符串中 x , y x,y x,y 的出现次数大于 0 0 0,即 r − l + 1 ⩾ k r-l+1 \geqslant k rl+1k p r e x [ r + 1 ] > p r e y [ r + 1 ] pre_x[r+1]>pre_y[r+1] prex[r+1]>prey[r+1] p r e x [ l ] > p r e y [ l ] pre_x[l]>pre_y[l] prex[l]>prey[l]
  • 本题求最大差值,在右端点固定的情况下,要想使得 p r e x [ r + 1 ] − p r e y [ r + 1 ] − ( p r e x [ l ] − p r e y [ l ] ) pre_x[r+1]-pre_y[r+1]-(pre_x[l]-pre_y[l]) prex[r+1]prey[r+1](prex[l]prey[l]) 越大,就是要 p r e x [ l ] − p r e y [ l ] pre_x[l]-pre_y[l] prex[l]prey[l] 的值越小,所以需要维护 p r e x [ l ] − p r e y [ l ] pre_x[l]-pre_y[l] prex[l]prey[l] 的最小值。又因为本题要求子字符串中 x x x 的出现次数必须为奇数, y y y 的出现次数必须为偶数( > 0 >0 >0),这里可以使用数组 m e m o [ p ] [ q ] memo[p][q] memo[p][q] 来记录 x x x y y y 的出现次数是为 p p p q q q 时, p r e x [ l ] − p r e y [ l ] pre_x[l]-pre_y[l] prex[l]prey[l] 的最小值( p , q p,q p,q 只表示奇偶性)
  • 更新答案 a n s = m a x ( a n s , p r e x [ r + 1 ] − p r e y [ r + 1 ] − m e m o [ p ] [ q ] ) ans = max(ans,pre_x[r+1]-pre_y[r+1]-memo[p][q]) ans=max(ans,prex[r+1]prey[r+1]memo[p][q]),这里的 p p p 的奇偶性与 p r e x [ r + 1 ] pre_x[r+1] prex[r+1] 相反, q q q 的奇偶性与 p r e y [ r + 1 ] pre_y[r+1] prey[r+1] 相同。

代码如下:

class Solution {public int maxDifference(String s, int k) {final int inf = Integer.MAX_VALUE/2;int n = s.length();int ans = -inf;for(int x = 0; x < 5; x++){for(int y = 0; y < 5; y++){if(x == y) continue;int[] pre_x = new int[n+1];int[] pre_y = new int[n+1];int[][] memo = {{inf, inf}, {inf, inf}};for(int l = 0, r = 0; r < n; r++){int a = s.charAt(r) - '0';pre_x[r+1] = pre_x[r] + (a == x ? 1 : 0);pre_y[r+1] = pre_y[r] + (a == y ? 1 : 0);// r - l + 1 >= k// pre_x[r+1] > pre_x[l]// pre_y[r+1] > pre_y[l]while(r - l + 1 >= k && pre_x[r+1] > pre_x[l] && pre_y[r+1] > pre_y[l]){int p = pre_x[l] & 1;int q = pre_y[l] & 1; memo[p][q] = Math.min(memo[p][q], pre_x[l] - pre_y[l]);l++;}//子字符串长度大于等于 k,才能更新答案if(r + 1 >= k)ans = Math.max(ans, pre_x[r+1] - pre_y[r+1] - memo[pre_x[r+1] & 1 ^ 1][pre_y[r+1] & 1]);}}}return ans;}
}

http://www.ppmy.cn/embedded/161839.html

相关文章

git 提示 fatal: The remote end hung up unexpectedly

我在 git push 的时候遇到报错 fatal: The remote end hung up unexpectedly 解决方法如下&#xff1a; 1. 调整缓存限制&#xff08;大文件推送&#xff09; git config --global http.postBuffer 524288000 # 设置缓存为500MB git config --global https.postBuffer 52428…

ClickHouse的前世今生

ClickHouse是一款由Yandex开发的高性能列式存储数据库管理系统,专为在线分析处理(OLAP)设计,适用于实时数据分析、大规模数据处理和复杂查询场景。以下是关于ClickHouse的安装、使用及应用场景的详细介绍: 一、ClickHouse的安装 ClickHouse支持多种操作系统,包括Linux、…

Cables Finance 构建集成LST与外汇RWA永续合约的综合性DEX

虽然 DeFi 领域整体发展迅速&#xff0c;但仍旧缺乏交易体验。现阶段市场已拓展至 RWAs 、永续期货和外汇领域&#xff0c;但跨资产交易的实际操作仍充满阻力。交易者面临流动性碎片化、抵押品被锁定在质押合约中缺乏流动性&#xff0c;以及整个系统仍围绕美元稳定币运转等问题…

Netty如何优雅地解决TCP粘包、拆包问题

引言 在TCP/IP协议族中&#xff0c;TCP&#xff08;传输控制协议&#xff09;是一个面向连接的、可靠的、基于字节流的传输层协议。TCP协议确保了数据能够可靠地从一个端点传输到另一个端点&#xff0c;但它并没有提供消息边界的概念。这意味着&#xff0c;当数据被发送时&…

C语言操作符详解

引言 C语言作为一种强大而灵活的编程语言&#xff0c;操作符是其重要组成部分。操作符用于执行各种运算&#xff0c;如算术运算、逻辑运算、比较运算等。深入理解C语言操作符&#xff0c;能帮助开发者编写出高效、准确的代码。 算术操作符 基本算术操作符 - &#xff08;加法…

社区版IDEA中配置TomCat(详细版)

文章目录 1、下载Smart TomCat2、配置TomCat3、运行代码 1、下载Smart TomCat 由于小编的是社区版&#xff0c;没有自带的tomcat server&#xff0c;所以在设置的插件里面搜索&#xff0c;安装第一个&#xff08;注意&#xff1a;安装时一定要关闭外网&#xff0c;小编因为这个…

java: framework from BLL、DAL、IDAL、MODEL、Factory using oracle

oracel 21c sql: -- 创建 School 表 CREATE TABLE School (SchoolId CHAR(5) NOT NULL,SchoolName NVARCHAR2(500) NOT NULL,SchoolTelNo VARCHAR2(8) NULL,PRIMARY KEY (SchoolId) );CREATE OR REPLACE PROCEDURE addschool(p_school_id IN CHAR,p_school_name IN NVARCHAR2,p…

笔记5——元组tuple

元组tuple tuple:一系列按特定顺序排列的元素组成 使用小括号 () 定义&#xff0c;元素之间用 , 隔开 my_tuple (I,love,endless,money) print(my_tuple)特点 不可变 &#xff1a;一旦创建&#xff0c;元组里的元素就不能被修改、添加或删除 可包含任意数据类型 有序性…