2023-05-22:给定一个长度为 n 的字符串 s ,其中 s[i] 是: D 意味着减少; I 意味着增加。 有效排列 是对有 n + 1 个在 [0, n] 范围内的整数的一个排列 perm
2023-05-22:给定一个长度为 n 的字符串 s ,其中 s[i] 是:
D 意味着减少;
I 意味着增加。
有效排列 是对有 n + 1 个在 [0, n] 范围内的整数的一个排列 perm ,使得对所有的 i:
如果 s[i] == 'D',那么 perm[i] > perm[i+1],以及;
如果 s[i] == 'I',那么 perm[i] < perm[i+1]。
返回 有效排列 perm的数量 。因为答案可能很大,所以请返回你的答案对 10^9 + 7 取余。
输入:s = "DID"。
输出:5。
答案2023-05-22:
算法1:暴力枚举
1.定义递归函数 ways(s []byte, i int, less int, n int) int,其中 s 为要判断的字符串,i 表示当前要填入的位置,less 记录上一个数的大小信息,n 表示总共有 n + 1 个数字需要填。
2.如果 i 等于 n,则返回 1,表示已经填完了。
3.如果 i 等于 0 或 s[i-1] 等于 'D',则循环从 0 到 less - 1 枚举下一个数 nextLess,并将结果加到 ans 上。每次递归调用时将 i 增加 1,并更新 less 的值为 nextLess。最后返回 ans。
4.否则 s[i-1] 等于 'I',则循环从 less 到 n-i 枚举下一个数 nextLess,并将结果加到 ans 上。每次递归调用时将 i 增加 1,并更新 less 的值为 nextLess。最后返回 ans。
时间复杂度:O(n!),其中 n 为数字序列的长度。
空间复杂度:O(n),递归过程中需要 O(n) 的栈空间。
算法2:动态规划
1.定义二维数组 dp,其中 dp[i][j] 表示在第 i 个位置填入数字 j 的情况下满足条件的排列的数量。
2.初始化 dp[n][less] 为 1,表示在最后一个位置填入 less 的数量只有一种。
3.从倒数第二个位置开始往前遍历,根据当前位置 s[i-1] 的值,分别枚举下一个数字的大小。如果 s[i-1] 等于 'D',则循环从 0 到 less - 1 枚举下一个数字的大小,将 dp[i][less] 增加上 dp[i+1][nextLess],最后取模。
4.如果 s[i-1] 等于 'I',则循环从 less 到 n-i 枚举下一个数字的大小,将 dp[i][less] 增加上 dp[i+1][nextLess],最后取模。
5.最终答案为 dp[0][n]。
时间复杂度:O(n^2),需要填充一个二维数组,数组大小为 n * (n+1)。
空间复杂度:O(n^2),需要使用一个二维数组来存储状态。
算法3:动态规划 + 优化
1.定义二维数组 dp,其中 dp[i][j] 表示在第 i 个位置填入数字 j 的情况下满足条件的排列的数量。
2.初始化 dp[n][less] 为 1,表示在最后一个位置填入 less 的数量只有一种。
3.从倒数第二个位置开始往前遍历,根据当前位置 s[i-1] 的值,分别枚举下一个数字的大小。如果 s[i-1] 等于 'D',则从 0 到 less 枚举 nextLess,将 dp[i][less] 增加上 dp[i+1][nextLess],最后取模。
4.如果 s[i-1] 等于 'I',则从 n-i 到 less 枚举 nextLess,将 dp[i][less] 增加上 dp[i+1][nextLess],最后取模。
5.在循环中记录当前已经累计的和 sum,然后 dp[i][less] 的值更新为 sum,同时需要考虑取模的问题。具体来说,如果当前的 sum 大于 mod,则减去一个 mod;如果当前的 sum 小于 0,则加上一个 mod。
6.最终答案为 dp[0][n]。
时间复杂度:O(n),只需填充一个一维数组即可。
空间复杂度:O(n),只需使用一个一维数组来存储状态。
go完整代码如下:
package main
import "fmt"
func numPermsDISequence1(s string) int {
n := len(s) + 1
return ways1([]byte(s), 0, n, n)
}
func ways1(s []byte, i int, less int, n int) int {
if i == n {
return 1
} else if i == 0 || s[i-1] == 'D' {
ans := 0
for nextLess := 0; nextLess < less; nextLess++ {
ans += ways1(s, i+1, nextLess, n)
}
return ans
} else { // s[i-1] = 'I'
ans := 0
for nextLess := less; nextLess < n-i; nextLess++ {
ans += ways1(s, i+1, nextLess, n)
}
return ans
}
}
func numPermsDISequence2(s string) int {
mod := 1000000007
n := len(s) + 1
dp := make([][]int, n+1)
for i := range dp {
dp[i] = make([]int, n+1)
}
for less := 0; less <= n; less++ {
dp[n][less] = 1
}
for i := n - 1; i >= 0; i-- {
for less := 0; less <= n; less++ {
if i == 0 || s[i-1] == 'D' {
for nextLess := 0; nextLess < less; nextLess++ {
dp[i][less] = (dp[i][less] + dp[i+1][nextLess]) % mod
}
} else {
for nextLess := less; nextLess < n-i; nextLess++ {
dp[i][less] = (dp[i][less] + dp[i+1][nextLess]) % mod
}
}
}
}
return dp[0][n]
}
func numPermsDISequence3(s string) int {
mod := 1000000007
n := len(s) + 1
dp := make([][]int, n+1)
for i := range dp {
dp[i] = make([]int, n+1)
}
for less := 0; less <= n; less++ {
dp[n][less] = 1
}
for i := n - 1; i >= 0; i-- {
if i == 0 || s[i-1] == 'D' {
for less := 0; less <= n; less++ {
if less > 0 {
dp[i][less] = (dp[i][less-1] + dp[i+1][less-1]) % mod
} else {
dp[i][less] = 0
}
}
} else { // s[i-1] = 'I'
dp[i][n-i-1] = dp[i+1][n-i-1]
for less := n - i - 2; less >= 0; less-- {
dp[i][less] = (dp[i][less+1] + dp[i+1][less]) % mod
}
}
}
return dp[0][n]
}
func main() {
s := "DID"
res := numPermsDISequence1(s)
fmt.Println(res)
res = numPermsDISequence2(s)
fmt.Println(res)
res = numPermsDISequence3(s)
fmt.Println(res)
}

rust语言完整代码如下:
fn num_perms_di_sequence1(s: String) -> i32 {
let s = s.as_bytes();
let n = s.len() + 1;
ways1(s, 0, n, n)
}
// i : 填的数字的位
// 3 5 2
// 0 1 2
// I D
// less :
// 之前填的数字X,后面剩下的数字中有几个比X小!
// X
// i-1 i
fn ways1(s: &[u8], i: usize, less: usize, n: usize) -> i32 {
if i == n {
return 1;
} else if i == 0 || s[i - 1] == b'D' {
(0..less)
.map(|next_less| ways1(s, i + 1, next_less, n))
.sum()
} else {
// s[i-1] = b'I'
((less as isize)..((n - i) as isize))
.map(|next_less| ways1(s, i + 1, next_less as usize, n))
.sum()
}
}
fn num_perms_di_sequence2(s: String) -> i32 {
let s = s.as_bytes();
let n = s.len() + 1;
let mod_num = 1000000007;
let mut dp = vec![vec![0; n + 1]; n + 1];
for less in 0..=n {
dp[n][less] = 1;
}
let mut i = n as i32 - 1;
while i >= 0 {
for less in 0..=n {
if i == 0 || s[(i - 1) as usize] == b'D' {
for next_less in 0..less {
dp[i as usize][less] =
(dp[i as usize][less] + dp[i as usize + 1][next_less]) % mod_num;
}
} else {
// s[i-1] = b'I'
for next_less in less..n - i as usize {
dp[i as usize][less] =
(dp[i as usize][less] + dp[i as usize + 1][next_less]) % mod_num;
}
}
}
i -= 1;
}
dp[0][n]
}
fn num_perms_di_sequence3(s: String) -> i32 {
let s = s.as_bytes();
let n = s.len() + 1;
let mod_num = 1000000007;
let mut dp = vec![vec![0; n + 1]; n + 1];
for less in 0..=n {
dp[n][less] = 1;
}
let mut i = n as i32 - 1;
while i >= 0 {
if i == 0 || s[i as usize - 1] == b'D' {
for less in 0..=n {
dp[i as usize][less] = if less > 0 {
(dp[i as usize][less - 1] + dp[i as usize + 1][less - 1]) % mod_num
} else {
0
}
}
} else {
// s[i-1] = b'I'
dp[i as usize][n - i as usize - 1] = dp[i as usize + 1][n - i as usize - 1];
let mut less = n as i32 - i - 2;
while less >= 0 {
dp[i as usize][less as usize] = (dp[i as usize][less as usize + 1]
+ dp[i as usize + 1][less as usize])
% mod_num;
less -= 1;
}
}
i -= 1;
}
dp[0][n]
}
fn main() {
let s = String::from("DID");
let res = num_perms_di_sequence1(s);
println!("{}", res);
let s = String::from("DID");
let res = num_perms_di_sequence2(s);
println!("{}", res);
let s = String::from("DID");
let res = num_perms_di_sequence3(s);
println!("{}", res);
}

c语言完整代码如下:
#include <stdio.h>
#include <stdlib.h>
int ways1(char* s, int i, int less, int n);
int numPermsDISequence1(char* s);
int numPermsDISequence2(char* str);
int numPermsDISequence3(char* str);
int main() {
char s[] = "DID";
printf("%d\n", numPermsDISequence1(s));
printf("%d\n", numPermsDISequence2(s));
printf("%d\n", numPermsDISequence3(s));
return 0;
}
int numPermsDISequence1(char* s) {
return ways1(s, 0, strlen(s) + 1, strlen(s) + 1);
}
int ways1(char* s, int i, int less, int n) {
int ans = 0;
if (i == n) {
ans = 1;
}
else if (i == 0 || *(s + i - 1) == 'D') {
for (int nextLess = 0; nextLess < less; nextLess++) {
ans += ways1(s, i + 1, nextLess, n);
}
}
else {
for (int nextLess = less; nextLess < n - i; nextLess++) {
ans += ways1(s, i + 1, nextLess, n);
}
}
return ans;
}
int numPermsDISequence2(char* s) {
int mod = 1000000007;
int n = strlen(s) + 1;
int** dp = (int**)malloc((n + 1) * sizeof(int*));
for (int i = 0; i <= n; i++) {
dp[i] = (int*)malloc((n + 1) * sizeof(int));
}
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= n; j++) {
dp[i][j] = 0;
}
}
for (int less = 0; less <= n; less++) {
dp[n][less] = 1;
}
for (int i = n - 1; i >= 0; i--) {
for (int less = 0; less <= n; less++) {
if (i == 0 || s[i - 1] == 'D') {
for (int nextLess = 0; nextLess < less; nextLess++) {
dp[i][less] = (dp[i][less] + dp[i + 1][nextLess]) % mod;
}
}
else {
for (int nextLess = less; nextLess < n - i; nextLess++) {
dp[i][less] = (dp[i][less] + dp[i + 1][nextLess]) % mod;
}
}
}
}
int res = dp[0][n];
for (int i = 0; i <= n; i++) {
free(dp[i]);
}
free(dp);
return res;
}
int numPermsDISequence3(char* s) {
int mod = 1000000007;
int n = strlen(s) + 1;
int** dp = (int**)malloc((n + 1) * sizeof(int*));
for (int i = 0; i <= n; i++) {
dp[i] = (int*)malloc((n + 1) * sizeof(int));
}
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= n; j++) {
dp[i][j] = 0;
}
}
for (int less = 0; less <= n; less++) {
dp[n][less] = 1;
}
for (int i = n - 1; i >= 0; i--) {
if (i == 0 || s[i - 1] == 'D') {
for (int less = 0; less <= n; less++) {
dp[i][less] = less - 1 >= 0 ? ((dp[i][less - 1] + dp[i + 1][less - 1]) % mod) : 0;
}
}
else { // s[i-1] = 'I'
dp[i][n - i - 1] = dp[i + 1][n - i - 1];
for (int less = n - i - 2; less >= 0; less--) {
dp[i][less] = (dp[i][less + 1] + dp[i + 1][less]) % mod;
}
}
}
int res = dp[0][n];
for (int i = 0; i <= n; i++) {
free(dp[i]);
}
free(dp);
return res;
}

c++完整代码如下:
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
int ways1(vector<char>& s, int i, int less, int n);
int numPermsDISequence1(string s);
int numPermsDISequence2(string s);
int numPermsDISequence3(string s);
// i : 填的数字的位
// 3 5 2
// 0 1 2
// I D
// less :之前填的数字X,后面剩下的数字中有几个比X小!
// X
// i-1 i
int ways1(vector<char>& s, int i, int less, int n) {
int ans = 0;
if (i == n) {
ans = 1;
}
else if (i == 0 || s[i - 1] == 'D') {
for (int nextLess = 0; nextLess < less; nextLess++) {
ans += ways1(s, i + 1, nextLess, n);
}
}
else { // s[i-1] = 'I'
for (int nextLess = less; nextLess < n - i; nextLess++) {
ans += ways1(s, i + 1, nextLess, n);
}
}
return ans;
}
int numPermsDISequence1(string s) {
vector<char> str(s.begin(), s.end());
str.push_back('I');
return ways1(str, 0, s.length() + 1, s.length() + 1);
}
int numPermsDISequence2(string s) {
int mod = 1000000007;
vector<char> str(s.begin(), s.end());
str.push_back('I');
int n = str.size();
vector<vector<int>> dp(n + 1, vector<int>(n + 1));
for (int less = 0; less <= n; less++) {
dp[n][less] = 1;
}
for (int i = n - 1; i >= 0; i--) {
for (int less = 0; less <= n; less++) {
if (i == 0 || str[i - 1] == 'D') {
for (int nextLess = 0; nextLess < less; nextLess++) {
dp[i][less] = (dp[i][less] + dp[i + 1][nextLess]) % mod;
}
}
else {
for (int nextLess = less; nextLess < n - i; nextLess++) {
dp[i][less] = (dp[i][less] + dp[i + 1][nextLess]) % mod;
}
}
}
}
return dp[0][n];
}
int numPermsDISequence3(string s) {
int mod = 1000000007;
vector<char> str(s.begin(), s.end());
str.push_back('I');
int n = str.size();
vector<vector<int>> dp(n + 1, vector<int>(n + 1));
for (int less = 0; less <= n; less++) {
dp[n][less] = 1;
}
for (int i = n - 1; i >= 0; i--) {
if (i == 0 || str[i - 1] == 'D') {
for (int less = 0; less <= n; less++) {
dp[i][less] = less - 1 >= 0 ? ((dp[i][less - 1] + dp[i + 1][less - 1]) % mod) : 0;
}
}
else { // str[i-1] = 'I'
dp[i][n - i - 1] = dp[i + 1][n - i - 1];
for (int less = n - i - 2; less >= 0; less--) {
dp[i][less] = (dp[i][less + 1] + dp[i + 1][less]) % mod;
}
}
}
return dp[0][n];
}
int main() {
string s = "DID";
cout << numPermsDISequence1(s) << endl; // expect 5
cout << numPermsDISequence2(s) << endl; // expect 5
cout << numPermsDISequence3(s) << endl; // expect 5
return 0;
}

2023-05-22:给定一个长度为 n 的字符串 s ,其中 s[i] 是: D 意味着减少; I 意味着增加。 有效排列 是对有 n + 1 个在 [0, n] 范围内的整数的一个排列 perm的更多相关文章
- 4.写一个控制台应用程序,接收一个长度大于3的字符串,完成下列功能: 1)输出字符串的长度。 2)输出字符串中第一个出现字母a的位置。 3)在字符串的第3个字符后面插入子串“hello”,输出新字符串。 4)将字符串“hello”替换为“me”,输出新字符串。 5)以字符“m”为分隔符,将字符串分离,并输出分离后的字符串。 */
namespace test4 {/* 4.写一个控制台应用程序,接收一个长度大于3的字符串,完成下列功能: 1)输出字符串的长度. 2)输出字符串中第一个出现字母a的位置. 3)在字符串的第3个字符 ...
- C语言:利用指针解决:统计一个长度为2的字符串在另外一个字符串中出现的次数。
//统计一个长度为2的字符串在另外一个字符串中出现的次数. #include <conio.h> #include <stdio.h> #include <string. ...
- 前端面试题:不使用loop循环,创建一个长度为100的数组,并且每个元素的值等于它的下标,,怎么实现好?
昨天,看这道题,脑子锈住了,就是没有思路,没看明白是什么意思?⊙﹏⊙|∣今天早上起床,想到需要思考一下这个问题. 当然,我没想明白为什么要这样做?(创建一个长度为100的数组,并且每个元素的值等于它的 ...
- 给定数组a[1,2,3],用a里面的元素来生成一个长度为5的数组,打印出其排列组合
给定数组a[1,2,3],用a里面的元素来生成一个长度为5的数组,打印出其排列组合 ruby代码: def all_possible_arr arr, length = 5 ret = [] leng ...
- java—数组乘积输入: 一个长度为n的整数数组input 输出: 一个长度为n的数组result,满足result[i] = input数组中,除了input[i] 之外的所有数的乘积,不用考虑溢出例如 input {2, 3, 4, 5} output: {60, 40, 30, 24}
/** * 小米关于小米笔试题 数组乘积输入: 一个长度为n的整数数组input 输出: 一个长度为n的数组result,满足result[i] = * input数组中,除了input[i] 之外的 ...
- ACM学习之路————一个大整数与一个小整数不得不说得的秘密
这个相对于两个大整数的运算来说,只能说是,low爆了. 只要利用好除法的性质,这类题便迎刃而解.O(∩_∩)O哈哈~ //大整数除一个int数 #include<iostream> #in ...
- 面试题:给定一个长度为N的数组,其中每个元素的取值范围都是1到N。判断数组中是否有重复的数字
题目:给定一个长度为N的数组,其中每个元素的取值范围都是1到N.判断数组中是否有重复的数字.(原数组不必保留) 方法1.对数组进行排序(快速,堆),然后比较相邻的元素是否相同.时间复杂度为O(nlog ...
- 给定一个set字符和一个正数k,找出所有该做set它可以由长度构成k该字符串集合 print-all-combinations-of-given-length
// 给定一个set字符和一个正数k,找出所有该做set它可以由长度构成k该字符串集合 /* Input: set[] = {'a', 'b'}, k = 3 Output: aaa aab aba ...
- python中有两个下划线__的是内置方法,一个下划线_或者没有下划线的可能是属性,也可能是方法,也可能是类名
python中有两个下划线__的是内置方法,一个下划线_或者没有下划线的可能是属性,也可能是方法,也可能是类名,如果在类中定义的就是类的私有成员. >>> dir(__builtin ...
- js random获取随机数,获取任意范围内随机整数
壹 ❀ 引 想着好久没做笔试题了,去GitHub找了面试相关的项目,结果被第一道题难住了.....说难其实也不难,而是我忘记了取范围随机整数怎么写了,不可否认如果当时是我在笔试,肯定也凉了,那么就由 ...
随机推荐
- sql处理重复的列,更好理清分组和分区
一.分组统计.分区排名 1.语法和含义: 如果查询结果看得有疑惑,看第二部分-sql处理重复的列,更好理清分组和分区,有建表插入数据的sql语句 分组统计:GROUP BY 结合 统计/聚合函数一起使 ...
- MyBatis详细代码来啦!
家人们,改代码改到现在真的绝了,终于是改出来了,但是对于某些判断性的小问题还没写,细节性满满的增删改查终于实现啦! 目录结构 各个文件的代码: //SqlSessionFactoryUtils.jav ...
- 如何让excel不转换科学技术法
使用场景: 业务部门从系统导出数据给开发人员,打开后数字全部变为科学计数法 参考文章:https://www.zhihu.com/question/20096750
- 手把手 Golang 实现静态图像与视频流人脸识别
说起人脸识别,大家首先想到的实现方式应该是 Python 去做相关的处理,因为相关的机器学习框架,库都已经封装得比较好了.但是我们今天讨论的实现方式换成 Golang,利用 Golang 去做静态图像 ...
- C#中的数据字典Dictionary
前言 今天上午和往常一样在网上冲浪,看到码甲哥微信群里面在聊一个面试题,比较有意思,这里简单分享下结论中的Dictionary字典. 有50w个int类型的数字,现在需要判断一下里面是否存在重复的数字 ...
- java 实现文件夹上传(springBoot 框架)
有时我们后台管理等服务可能会有这样一个简单需求,就是根据文件夹将整个文件夹下的所有资源都上传到我们的服务器上,本人也是搜索了大量资料,最终以最简单便捷的方式实现该功能,具体操作步骤如下 一.前端如何设 ...
- React的组件化/工程化开发(脚手架)
脚手架: create-react-app 安装脚手架: $ npm i create-react-app -g 检查安装: $ npm create-react-app --version 新建项目 ...
- MySQL事务还没提交,Canal就能读到消息了?
[问题描述] 开发有天碰到一个很奇怪的问题,他的场景是这样子的: 通过Canal来订阅MySQL的binlog, 当捕获到有数据变化时,回到数据库,反查该数据的明细,然后做进一步处理. 有一次,他碰到 ...
- R语言文本挖掘细胞词库的转换
搜狗细胞词库解析 一. 加载R包转换 library(rJava) library(Rwordseg) write.csv(as.data.frame(importSogouScel('wuliu.s ...
- [软件设计&系统建模] Web软件通用能力模块
0 基础工具 1 日志 2 权限 3 文件处理(下载/上传) 4 对象池 对象池 数据库连接池 线程池 5 微服务 服务网关 配置中心 注册中心 服务调用 服务熔断 健康检测 Actuator 6 缓 ...