5492. 分割字符串的方案数 #组合公式 #乘法原理 #区间分割

题目链接

题意

给定01二进制串\(s\),可将\(s\)分割为三个非空 字符串\(s_1,s_2,s_3\),即(\(s_1+s_2+s_3=s\))。现要你求出分割\(s\)的方案数,保证\(s_1,s_2,s_3\)中字符1的数目相同(对\(1e9+7\)取模),他们的长度不一定相等

分析

举个例子,01100011000101串,可以知道三个子串必须包含2个'1',我们观察到左子串的界限,可以如下划分:011|000110001010110|001100010101100|011000101011000|11000101,共四种划分方案;同理对于右子串,共有四种划分方案。当我们将左右子串由于中间子串的间隔,使得左右子串的确定不会相互影响,同时中间子串也相应确定下来,通过乘法原理,总方案数=左子串划分方案数\(\times\)右子串划分方案数=16。

然而,别忘了诸如00000等只包含'0'的串,三子串的划分确定会相互影响,比如0|000|0000|0|0等,此时我们可以用高中所学排列组合的“挡板法”确定下来,即串长为\(n\),有\(n-1\)空位,可以插入两个挡板,即\(C^2_{n-1}\)。

typedef long long ll;
class Solution {
private:
int sum[100005];
const int MOD = 1e9 + 7;
public:
int numWays(string s) {
int n = s.size();
for (int i = 0; i < n; i++) //利用前缀和统计1的数目
sum[i + 1] = sum[i + 1 - 1] + (s[i] == '1');
if(sum[n] == 0){ //特判全部为0的串
ll ans = (ll)(n - 1) * (ll)(n - 2) / (ll)2;
return ans % MOD;
}
if(sum[n] % 3 != 0) return 0; //特判不含有3的整数倍的串,无法分割
else{
int diff = sum[n] / 3; //确定每个子串中的'1'数量
ll a = 0, b = 0;
for (int i = 1; i <= n - 2; i++) //确定左子串可拓展的长度
if(sum[i] == diff) a++;
for (int i = n; i >= 2; i--) //确定右子串可拓展的长度
if(sum[n] - sum[i - 1] == diff) b++;
ll ans = (a % MOD) * (b % MOD); //乘法原理
return ans % MOD;
}
}
};

5493. 删除最短的子数组使剩余数组有序 #归并排序 #区间分割

题目链接

题意

给定整数数组arr ,你需要删除一个子数组(原数组中连续的一个子序列,可以为空),使得arr中剩下的元素是 非递减的。现要你求出满足题目要求的最短子数组的长度。

分析

感谢@Liuyh思路。

题目要求只能删除一个子数组,也就说子数组内部存在一小段是非递减的,但也必须要删去。一般地,我们一定是从数组中间部分进行删除(只删除左部分或只删除右部分属于退化情况),即[....|XXXX|....](X表示要删除的部分)。 删除中间的子数组(并不代表最终删除子数组),意味着剩余前后两个子数组都符合非递减,这一操作需要前后两个指针,分别将两数组边界确定下来。代码中左子数组为[0, lo],而右子数组为[hi, len-1]。比如原数组[1,2,3,10,4,2,3,5],确定出左子数组 [1,2,3,10]lo指向10,右子数组[2, 3, 5]。中间数组删除长度为\(hi-lo+1\)

现在我们要合并上述两个子数组,需要用到归并排序的思想,一旦发现右子数组比左子数组还大的元素,其中一个元素给舍弃掉(无需考虑是删除左数组的还是右数组的)。举个例子:

  • [1,2,3,10][2,3,5]
  • 由于1<2,此时[2,3,10][2,3,5]
  • 由于2<=2,此时[3,10][2,3,5]
  • 由于3>2,舍弃右子数组的2,左子数组跳过3ans++,此时[10][3,5]
  • 由于10>3,舍弃10,得到 [][5],算法结束。
class Solution {
public:
int findLengthOfShortestSubarray(vector<int>& arr) {
int lo = 0, len = arr.size(), hi = arr.size() - 1;
if(len == 1) return 0; //特判:一个元素就无需删除了
while(lo + 1 < len && arr[lo] <= arr[lo + 1]) lo++;
//开始分割,确定左区间的右端点,注意,是往后递推,这样能够保证lo最终指向的依然是非降左子序列的右端点
if(lo + 1 == len) return 0; //说明原数组是个非降序列,直接返回0
while(lo < hi && arr[hi - 1] <= arr[hi]) hi--;
if(hi == lo && hi == 0) return len - 1; //说明原数组是完全递减区间 int ans = hi - lo - 1; //统计分割出来的区间
int i = 0, j = hi; while(i <= lo && j < len){ //合并区间
if(arr[i] <= arr[j]) i++; //以左序列为基准
else if(arr[i] > arr[j]){ //因为题目要求从左至右递增
i++; j++;//注意!一定是两个指针同时前进,因为你不知道哪个子数组影响最终结果
ans++;
}
}
return ans;
}
};

5494. 统计所有可行路径 #记忆化搜索

题目链接

题意

有若干个城市,第i个城市有location[i]值。给定你城市出发起点start、目的地城市finish、初始汽油总量fuel。每当你从城市j移动到城市i时,消耗的油量为|location[j] - location[i]|。你要保证剩余的油量非负,方能移动到其他城市。同时,你可以经过任意城市超过一次(包括startfinish)。现要你求出从startfinish可能路径的数目(需取模)

分析

观察到数据范围\(fuel\leq200\)及\(locations.len\leq100\),直接记忆化搜索即可。但注意,尽管你此时到达了finish城市,只要你油量足够,仍能够移动到其他城市。

dp[i][j]表示当前起点为i,剩余油量j的总方案数。

要注意,我直接把dp数组放到全局变量的时候,出锅了不少qaq,别忘了在类内要对这个全局变量初始化一下,同时记忆化搜索一般赋值为-1较为稳妥。

typedef long long ll;
int dp[105][205];
const int MOD = 1e9 + 7;
class Solution {
public:
int dfs(vector<int>& locations, int start, int finish, int fuel){
if(dp[start][fuel] != -1) return dp[start][fuel];
ll ans = 0; int len = locations.size();
if(start == finish) ans++;
for (int i = 0; i < len; i++){
int diff = abs(locations[i] - locations[start]);
if(start == i) continue;
if(fuel - diff >= 0){
ans = (ans + dfs(locations, i, finish, fuel - diff)) % MOD;
}
}
dp[start][fuel] = (ans % MOD);
return dp[start][fuel];
}
int countRoutes(vector<int>& locations, int start, int finish, int fuel) {
memset(dp, -1, sizeof(dp));
return dfs(locations, start, finish, fuel);
}
};

LeetCode双周赛#34的更多相关文章

  1. leetcode 双周赛9 进击的骑士

    一个坐标可以从 -infinity 延伸到 +infinity 的 无限大的 棋盘上,你的 骑士 驻扎在坐标为 [0, 0] 的方格里. 骑士的走法和中国象棋中的马相似,走 “日” 字:即先向左(或右 ...

  2. leetcode 双周赛9 找出所有行中最小公共元素

    给你一个矩阵 mat,其中每一行的元素都已经按 递增 顺序排好了.请你帮忙找出在所有这些行中 最小的公共元素. 如果矩阵中没有这样的公共元素,就请返回 -1. 示例: 输入:mat = [[,,,,] ...

  3. [每日一题2020.06.16] leetcode双周赛T3 5423 找两个和为目标值且不重叠的子数组 DP, 前缀和

    题目链接 给你一个整数数组 arr 和一个整数值 target . 请你在 arr 中找 两个互不重叠的子数组 且它们的和都等于 target .可能会有多种方案,请你返回满足要求的两个子数组长度和的 ...

  4. LeetCode双周赛#36

    1604. 警告一小时内使用相同员工卡大于等于三次的人 题目链接 题意 给定两个字符串数组keyName和keyTime,分别表示名字为keytime[i]的人,在某一天内使用员工卡的时间(格式为24 ...

  5. LeetCode双周赛#35

    1589. 所有排列中的最大和 #差分 #贪心 题目链接 题意 给定整数数组nums,以及查询数组requests,其中requests[i] = [starti, endi] .第i个查询求 num ...

  6. LeetCode双周赛#33 题解

    5480. 可以到达所有点的最少点数目 #贪心 题目链接 题意 给定有向无环图,编号从0到n-1,一个边集数组edges(表示从某个顶点到另一顶点的有向边),现要找到最小的顶点集合,使得从这些点出发, ...

  7. Leetcode 双周赛#32 题解

    1540 K次操作转变字符串 #计数 题目链接 题意 给定两字符串\(s\)和\(t\),要求你在\(k\)次操作以内将字符串\(s\)转变为\(t\),其中第\(i\)次操作时,可选择如下操作: 选 ...

  8. LeetCode第8场双周赛(Java)

    这次我只做对一题. 原因是题目返回值类型有误,写的是 String[] ,实际上应该返回 List<String> . 好吧,只能自认倒霉.就当涨涨经验. 5068. 前后拼接 解题思路 ...

  9. LeetCode 第 15 场双周赛

    1287.有序数组中出现次数超过25%的元素 1288.删除被覆盖区间 1286.字母组合迭代器 1289.下降路径最小和 II 下降和不能只保留原数组中最小的两个,hacked. 1287.有序数组 ...

随机推荐

  1. 浅谈分布式共识算法raft

    前言:在分布式的系统中,存在很多的节点,节点之间如何进行协作运行.高效流转.主节点挂了怎么办.如何选主.各节点之间如何保持一致,这都是不可不面对的问题,此时raft算法应运而生,专门 用来解决上述问题 ...

  2. LOJ 6068「2017 山东一轮集训 Day4」棋盘

    题意 一个 \(n\times n\) 的棋盘上面有若干障碍物. 定义两个棋子可以互相攻击当且仅当这两个棋子的横坐标或纵坐标相等而且中间不能隔着障碍物.(可以隔棋子) 有 \(q\) 次询问,每次询问 ...

  3. MySql基础(常用)

    MySQL常用语句 1.查看当前所有数据库 show databases; 2.打开指定的库 use 库名; 3.查看当前库中的所有表 show tables; 4.查看其他库的表 show tabl ...

  4. map+area标签

    map标签是用于定义一个客户端的图像映射即带有可点击区域的一幅图像,配合area标签 area 元素永远嵌套在 map 元素内部.area 元素可定义图像映射中的区域 例:要实现一幅地图上鼠标点击或者 ...

  5. nacos、ribbon和feign的简明教程

    nacos简明教程 为什么需要nacos? 在微服务架构中,微服务之间经常要相互通信和调用,而且一个服务往往存在多个实例来降低负荷或保证高可用.我们假定A服务要调用B服务,最简单的方式把B服务的地址和 ...

  6. R语言factor类型转numeric

    R 语言中为了进行数据分析,比如回归分析,这时候对于数据表格中的factor类型的数据会带来弊端,比如对因子的每一个数据都进行一次回归,这样就显得很复杂,且违背了我们的初衷,需要把factor转换为n ...

  7. B/S图书管理系统

    B/S图书管理系统 系统管理 ①新用户注册 ②用户信息修改:修改信息,修改密码 ③锁定用户 ④注销用户 书籍管理 ①新书入库 ②借书办理 ③还书办理 ④书记注销 个人管理 ①图书查询 ②借书单查询 ③ ...

  8. C# 8: 可变结构体中的只读实例成员

    在之前的文章中我们介绍了 C# 中的 只读结构体(readonly struct)[1] 和与其紧密相关的 in 参数[2]. 今天我们来讨论一下从 C# 8 开始引入的一个特性:可变结构体中的只读实 ...

  9. linux kernel 的 procfs sysfs 对查问题的帮助

    遇到进程卡死,没有gdb 符号表:只能strace 跟踪处理分析 排查过程: 1.ps -aux 查看卡死进程pid 2.strace -T -tt -e trace=all -p 查看卡死进程系统调 ...

  10. python 之路 《三》列表与元组

    我也试着把我写的东西给我的一些同学看,其实这只是我的经验还是比较建议先看书,或者在网上找相关的教学视频有了一定的基础之后再来看我写的文章,将我的经验与自己所学的知识相结合这样才会有所提高.有的同学建议 ...