首页 > 其他分享 >力扣周赛第01弹----思维 与 dp

力扣周赛第01弹----思维 与 dp

时间:2024-03-17 15:45:27浏览次数:20  
标签:周赛 01 word nums int 力扣 range 序列 dp

力扣周赛第01弹----思维 与 dp

一、成为 K 特殊字符串需要删除的最少字符数

题目

给你一个字符串 word 和一个整数 k

如果 |freq(word[i]) - freq(word[j])| <= k 对于字符串中所有下标 ij 都成立,则认为 wordk 特殊字符串

此处,freq(x) 表示字符 xword 中的出现频率,而 |y| 表示 y 的绝对值。

返回使 word 成为 k 特殊字符串 需要删除的字符的最小数量。

示例

输入:word = "aabcaba", k = 0

输出:3

解释:可以删除 2"a"1"c" 使 word 成为 0 特殊字符串。word 变为 "baba",此时 freq('a') == freq('b') == 2

提示:

  • \(1 <= word.length <= 10^5\)
  • \(0 <= k <= 10^5\)
  • word 仅由小写英文字母组成。

思路

  • ①因为题目中只有26个小写英文字母,所以最多只会出现26个频数
  • ②考虑将频数按照从小到达排序,枚举最后保存频数的最小值x
  • ③将剩余的大于x + k的频数,变成x + k,小于x + k的就直接保留,计算保留的最大值,然后用总频数 - 保留值,即为删除最小数量

代码

class Solution:
    def minimumDeletions(self, word: str, k: int) -> int:
        cnt = sorted(Counter(word).values())
        max_save = 0
        for i,x in enumerate(cnt):
            s = 0
            for y in cnt[i:]:
                s += min(y,x + k)
            max_save = max(max_save,s)
        return len(word) - max_save

二、求出所有子序列的能量和

题目

给你一个长度为 n 的整数数组 nums 和一个 整数 k 。一个整数数组的 能量 定义为和 等于 k 的子序列的数目。

请你返回 nums 中所有子序列的 能量和

由于答案可能很大,请你将它对 \(10^9 + 7\) 取余 后返回。

示例

输入: nums = [1,2,3], k = 3

输出: 6

解释:

总共有 5 个能量不为 0 的子序列:

  • 子序列 [1,2,3]2个和为3 的子序列:[3] 和 [1,2] 。
  • 子序列 [1,3] 1个和为3 的子序列:[3] 。
  • 子序列 [2,3] 1个和为3 的子序列:[3] 。
  • 子序列[1,2] 1个和为3 的子序列:[1,2]。
  • 子序列[3] 1个和为3 的子序列:[3] 。

所以答案为 2 + 1 + 1 + 1 + 1 = 6

提示:

  • \(1 <= n <= 100\)
  • \(1 <= nums[i] <= 10^4\)
  • \(1 <= k <= 100\)

思路一

  • ①设dp[i][j] 为从前i个数中选出子序列,子序列得到和为j的方案数的总和;

  • ②易知,dp[i][j] = dp[i - 1][j] * 2

  • ③同时, dp[i][j] = dp[i][j] + dp[i - 1][j - num[i]]

  • ④注意,dp[0][0] = 1的初始化

  • ⑤综上,可列出状态转移方程写出程序!

代码

MOD = int(1e9 + 7)
class Solution:
    def sumOfPower(self, nums: List[int], k: int) -> int:
        n = len(nums)
        dp = [[0 for _ in range(k + 1)]for _ in range(n + 1)]
        dp[0][0] = 1
        for i in range(n):
            for j in range(k + 1):
                dp[i + 1][j] = dp[i][j] * 2 % MOD
                if j >= nums[i]:
                    dp[i + 1][j] = (dp[i + 1][j] + dp[i][j - nums[i]]) % MOD
        return dp[n][k]

由于只用到了 i + 1i两个状态,所以第一位可以优化掉,不过第二维要从从后往前枚举!

MOD = int(1e9 + 7)
class Solution:
    def sumOfPower(self, nums: List[int], k: int) -> int:
        n = len(nums)
        dp = [0 for _ in range(k + 1)]
        dp[0] = 1
        for i in range(n):
            for j in range(k,-1,-1):  # 从后往前枚举
                dp[j] = dp[j] * 2 % MOD
                if j >= nums[i]:
                    dp[j] = (dp[j] + dp[j - nums[i]]) % MOD
        return dp[k]

思路二

  • ①对于nums = [1,2,3,4,5],k=3,考虑到如果我们知道1 + 2 = 3,那么包含 1、2 对和为k的子序列的贡献为 \(2^{5-2}\)

  • ②所以我们只要求出,和为k的,长度为m的子序列的个数cnt,就能求出贡献为 $ 2^{n - m} × cnt$

  • ③设dp[i][j][k] 为从前i个数中选出和为j,且长度为k的子序列的个数!

  • dp[i][j][k] = dp[i - 1][j][k] ->不选第i个物品

  • dp[i][j][k] = dp[i][j - nums[i]][k - 1] ->选第i个物品

代码

MOD = int(1e9 + 7)
class Solution:
    def sumOfPower(self, nums: List[int], k: int) -> int:
        n = len(nums)
        dp = [[[0] * (n + 1) for _ in range(k + 1)]for _ in range(n + 1)]
        for i in range(n + 1):
            dp[i][0][0] = 1
        for i in range(n):
            for j in range(1,k + 1):
                for c in range(1,n + 1):
                    if j >= nums[i]:
                        dp[i + 1][j][c] = dp[i][j][c] + dp[i][j - nums[i]][c - 1]
                        dp[i + 1][j][c] %= MOD
                    else:
                        dp[i + 1][j][c] = dp[i][j][c]
        ans = 0
        for i in range(1,n + 1):
            ans = (ans + pow(2,n - i,MOD) * dp[n][k][i]) % MOD
        return ans

这也是可以优化第一维的,这里就不再赘述!

标签:周赛,01,word,nums,int,力扣,range,序列,dp
From: https://www.cnblogs.com/gebeng/p/18078670

相关文章

  • P3302 [SDOI2013] 森林 题解
    题目链接:森林有意思的树上可持久化线段树变形题,建议先看这个:P2633Countonatree题解对于本题而言,我们重新阐述树上可持久化线段树的核心思想,对于点路径/边路径上的第\(k\)大问题,我们使用树上前缀和问题的思想,将其转化为可差性问题:一条路径上的权值线段树可以拆分为几棵权......
  • 【网站项目】012医院住院管理系统
    ......
  • 【每日算法】常见AIGC模型; 刷题:力扣单调栈
    上期文章【每日算法】理论:生成模型基础;刷题:力扣单调栈文章目录上期文章一、上期问题二、理论问题1、stablediffusion模型的网络架构2、T5的网络架构(Text-To-TextTransferTransformer模型)3、SDXL模型4、DALLE5、BPE编码6、为什么DDPM加噪声的幅度是不一致的?三、力......
  • LeetCode精选101刷题必备(C++)-附详细分类及解体说明
    分享一本leetcode刷题必备,互联网就业必备的免费书,非常好,值得推荐。感谢作者高畅无私整理和免费分享。本书介绍    本书分为算法和数据结构两大部分,又细分了十五个章节,详细讲解了刷LeetCode时常用的技巧。我把题目精简到了101道,一是呼应了本书的标题,二是不想让读......
  • 【洛谷 P8661】[蓝桥杯 2018 省 B] 日志统计 题解(滑动窗口+优先队列+双端队列+集合)
    [蓝桥杯2018省B]日志统计题目描述小明维护着一个程序员论坛。现在他收集了一份“点赞”日志,日志共有NNN行。其中每一行的格式是tsid,表示在......
  • 【洛谷 P8602】[蓝桥杯 2013 省 A] 大臣的旅费 题解(图论+深度优先搜索+树的直径+链式
    [蓝桥杯2013省A]大臣的旅费题目描述很久以前,T王国空前繁荣。为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。为节省经费,T国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达。同......
  • 代码随想录 第22天 | ● 235. 二叉搜索树的最近公共祖先 ● 701.二叉搜索树中的插入
    leetcode:701.二叉搜索树中的插入操作-力扣(LeetCode)classSolution{publicTreeNodeinsertIntoBST(TreeNoderoot,intval){//判断叶子结点,null说明到了,可以赋值。if(root==null){TreeNodenode=newTreeNode(val);return......
  • JOISC 2017 记录
    Day1T1Cultivation发现任何的两个操作之间时没有偏序关系的,也就是我们可以任意调整操作之间的顺序。那么本质不同的操作,可以用\(l,r,u,d\)四个数表示,分别表示向左/右/上/下移动的次数。假设我们已经确定了\(u,d\),则会出现\(O(n)\)类本质不同的行,而对于每一行,都会给\(l,r......
  • 【QT入门】VS2019+QT的开发环境配置
    声明:该专栏为本人学习Qt知识点时候的笔记汇总,希望能给初学的朋友们一点帮助(加油!) 往期回顾:【QT入门】什么是qt,发展历史,特征,应用,QtCreator-CSDN博客【QT入门】Windows平台下QT的编译过程_qt编译windows应用-CSDN博客【QT入门】VS2019+QT的开发环境配置一、安装流程1......
  • PTA L2-014 列车调度
    火车站的列车调度铁轨的结构如下图所示。两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有N条平行的轨道。每趟列车从入口可以选择任意一条轨道进入,最后从出口离开。在图中有9趟列车,在入口处按照{8,4,2,5,3,9,1,6,7}的顺序排队等待进入。如果要求它们必须按序号递减的顺......