本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 加入知识星球提问!

周赛 348 概览

T1. 最小化字符串长度(Medium)

  • 标签:散列表、计数

T2. 半有序排列(Easy)

  • 标签:散列表

T3. 查询后矩阵的和(Medium)

  • 标签:散列表

T4. 统计整数数目(Hard)

  • 标签:数位 DP、构造


T1. 最小化字符串长度(Medium)

https://leetcode.cn/problems/minimize-string-length/

题解(散列表 + 计数)

无论每个字符有多少,最终每个字符都会剩下 1 个,因此只需要记录字符种类数:

class Solution {
fun minimizedStringLength(s: String): Int {
return s.toHashSet().size
}
}

复杂度分析:

  • 时间复杂度:$O(n)$
  • 空间复杂度:$O(n)$

T2. 半有序排列(Easy)

https://leetcode.cn/problems/semi-ordered-permutation/

题解(模拟)

我们只需要考虑 1 和 n,每次操作可以把 1 向左边移动一位,或者将 n 向右移动一位,但是考虑到 1 和 n 的移动方向有交叉时,要减少一次操作次数。

class Solution {
fun semiOrderedPermutation(nums: IntArray): Int {
val n = nums.size
val i = nums.indexOf(1)
val j = nums.indexOf(n)
return i + (n - 1 - j) - if (i > j) 1 else 0
}
}

复杂度分析:

  • 时间复杂度:$O(n)$
  • 空间复杂度:$O(1)$

T3. 查询后矩阵的和(Medium)

https://leetcode.cn/problems/sum-of-matrix-after-queries/

题解(散列表)

这道题需要一点逆向思维,越靠后的操作会覆盖越靠前的操作,所以我们逆序遍历,并维护:

  • rowSet:操作过的行号(逆序)
  • colSet:操作过的列号(逆序)

那么,在每次行操作中可以填充的次数就是该行中没有被操作过的列数,而每次行操作中可以填充的次数就是该列中没有被操作过的行数。

class Solution {
fun matrixSumQueries(n: Int, queries: Array<IntArray>): Long {
var ret = 0L
val visitSet = Array(2) { HashSet<Int>() }
for (query in queries.reversed()) {
val type = query[0]
val index = query[1]
val value = query[2]
// 重复操作
if (visitSet[type].contains(index)) continue
// 这次操作可以填充的数字
ret += 1L * (n - visitSet[type xor 1].size) * value
visitSet[type].add(index)
}
return ret
}
}

复杂度分析:

  • 时间复杂度:$O(q)$
  • 空间复杂度:$O(n + q)$

T4. 统计整数数目(Hard)

https://leetcode.cn/problems/count-of-integers/

题解(数位 DP)

1、定义 f(n) 表示 [1,n] 中满足条件的好整数,那么原问题的解为:f(num2) - f(num1) + if(num1)

2、使用数位 DP:

以 n = 234 为例

  • isLimit:高位是否约束当前位。例如百位填 2 时,十位就受到高位约束只能填 0-3,否则可以填 0-9
  • isNum:高位是否为数字,这题不要考虑前导 0

3、定义 dfs(i:Int, sum:Int, isLimit:Int) 表示子问题中满足条件的个数

4、在备忘录中,isLimit 为 true 的子问题只会递归 1 次,可以不为 isLimit 提供记忆化维度:

class Solution {

    private val MOD = 1000000007

    fun count(num1: String, num2: String, min_sum: Int, max_sum: Int): Int {
return count(num2, min_sum, max_sum) - count(num1, min_sum, max_sum) + check(num1, min_sum, max_sum)
} private fun check(num: String, min_sum: Int, max_sum: Int): Int {
var sum = 0
for (c in num) sum += c - '0'
return if (sum in min_sum..max_sum) 1 else 0
} // 数位 DP
private fun count(num: String, min_sum: Int, max_sum: Int): Int {
fun dfs(num: String, memo: Array<IntArray>, i: Int, sum: Int, isLimit: Boolean): Int {
// 终止条件
if (sum > max_sum) return 0
if (i == num.length) return if (sum >= min_sum) 1 else 0
// 备忘录
if (!isLimit && memo[i][sum] != -1) return memo[i][sum]
// 上界
val upper = if (isLimit) num[i] - '0' else 9
var ret = 0
for (choice in 0 .. upper) {
ret = (ret + dfs(num, memo, i + 1, sum + choice , isLimit && choice == upper)) % MOD
}
// 备忘录
if (!isLimit) memo[i][sum] = ret
return ret
} val n = num.length
val m = Math.min(9 * n, max_sum) + 1
return dfs(num, Array(n) { IntArray(m) { -1 } }, 0, 0, true)
}
}

复杂度分析:

  • 时间复杂度:$O(10·n·m)$
  • 空间复杂度:$O(n·m)$

往期回顾

LeetCode 周赛 348(2023/06/05)数位 DP 模板学会了吗的更多相关文章

  1. HDU 2089 不要62(数位dp模板题)

    http://acm.hdu.edu.cn/showproblem.php?pid=2089 题意:求区间内不包含4和连续62的数的个数. 思路: 简单的数位dp模板题.给大家推荐一个好的讲解博客.h ...

  2. POJ 3286 How many 0's(数位DP模板)

    题目链接:http://poj.org/problem?id=3286 题目大意: 输入n,m,求[n,m]的所有数字中,0出现的总数是多少,前导零不算. 解题思路: 模板题,设dp[pos][num ...

  3. 数位dp模板 [dp][数位dp]

    现在才想到要学数位dp,我是不是很弱 答案是肯定的 以一道自己瞎掰的题为模板 //题: //输入数字n //从0枚举到n,计算这n+1个数中含有两位数a的数的个数 //如12930含有两位数93 #i ...

  4. 51nod 1009 数字1的数量(数位dp模板)

    给定一个十进制正整数N,写下从1开始,到N的所有正数,计算出其中出现所有1的个数. 例如:n = 12,包含了5个1.1,10,12共包含3个1,11包含2个1,总共5个1.   数位dp的模板题   ...

  5. 数位DP模板详解

    // pos = 当前处理的位置(一般从高位到低位) // pre = 上一个位的数字(更高的那一位) // status = 要达到的状态,如果为1则可以认为找到了答案,到时候用来返回, // 给计 ...

  6. 51nod 1009 - 数字1的数量 - [数位DP][模板的应用以及解释]

    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1009 基准时间限制:1 秒 空间限制:131072 KB 给 ...

  7. 【hdu6148】Valley Numer【数位dp模板题】

    题意 对于每组数据给出一个整数n(length(n)<=100),找出不大于n的数字中有多少是Valley Numer.对于Valley的定义是它每一位的数字要么是递增,要么是递减,要么是先递减 ...

  8. HDU 3555 Bomb(数位DP模板啊两种形式)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 Problem Description The counter-terrorists found ...

  9. HDU 2089 不要62 数位DP模板题

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089 参考博客:https://www.cnblogs.com/HDUjackyan/p/914215 ...

  10. HDU - 4722 Good Numbers 【找规律 or 数位dp模板】

    If we sum up every digit of a number and the result can be exactly divided by 10, we say this number ...

随机推荐

  1. 蓝桥杯十一届JavaA组-C++解题

    本人随便乱写,目前正确性未知 C.本质上升序列 #include<bits/stdc++.h> using namespace std; bool access[4][4]; int df ...

  2. 随机服务系统模拟—R实现(一)

    排队论--随机服务系统 日常生活中存在大量有形和无形的排队或拥挤现象,如旅客购票排队,市内电话占线等现象.排队论的基本思想是 1909 年丹麦数学家.科学家,工程师 A. K. 埃尔朗在解决自动电话设 ...

  3. 最简单Openwrt ipv6配置,局域网WAN6中继模式获取原生ipv6地址

    条件 condition wan 和 wan6 是默认配置     Wan and wan6 are the default configurations 同时wan6可以获取到原生IPv6     ...

  4. group_concat_max_len设置过小致group_concat()排列不全

    问题描述:group_concat_max_len默认值1024导致group_concat函数排列显示不足 group_concat_max_len长度显示跟group_concat排列长度息息相关 ...

  5. 没有杯子的世界:OOP设计思想的应用实践

    最近看到一个有趣的问题:Person类具有Hand,Hand可以操作杯子Cup,但是在石器时代是没有杯子的,这个问题用编程怎么解决? 简单代码实现 我们先用简单代码实现原问题: @Data publi ...

  6. 官宣 | Hugging Face 中文博客正式发布!

    作者:Tiezhen.Adina.Luke Hugging Face 的中国社区成立已经有五个月之久,我们也非常高兴的看到 Hugging Face 相关的中文内容在各个平台广受好评,我们也注意到,H ...

  7. boot-admin整合Quartz实现动态管理定时任务

    淄博烧烤爆红出了圈,当你坐在八大局的烧烤摊,面前是火炉.烤串.小饼和蘸料,音乐响起,啤酒倒满,烧烤灵魂的party即将开场的时候,你系统中的Scheduler(调试器),也自动根据设定的Trigger ...

  8. 关于聚合根,领域事件的那点事---深入浅出理解DDD

    作者:京东物流 赵勇萍 前言 最近有空会跟同事讨论DDD架构的实践落地的情况,但真实情况是,实际中对于领域驱动设计中的实体,值对象,聚合根,领域事件这些战术类的实践落地,每个人理解依然因人而异,大概率 ...

  9. [图像处理]仿射变换(Affine Transformation)

    文章目录 仿射变换(Affine Transformation) 平移变换 Translation 缩放变换(Scale) 剪切变换(Shear) 旋转变换(Rotation) 组合 仿射变换(Aff ...

  10. [Pytorch框架] 2.1.1 PyTorch 基础 : 张量

    文章目录 PyTorch 基础 : 张量 张量(Tensor) 基本类型 Numpy转换 设备间转换 初始化 常用方法 PyTorch 基础 : 张量 在第一章中我们已经通过官方的入门教程对PyTor ...