统计字典序元音字符串的数目(一题三解)
文章目录
- 前言
- 题目描述
- 回溯算法
- 动态规划
- 数学(盒子放球模型)
- 结语
前言
突然间发现自己好久没写有关算法题的博客了,今儿来一道很有意思的算法题,它可以使用三种完全不同的思路来处理,话不多说,直接上题。
题目描述
给你一个整数 n,请返回长度为 n 、仅由元音 (a, e, i, o, u) 组成且按 字典序排列 的字符串数量。
字符串 s 按 字典序排列 需要满足:对于所有有效的 i,s[i] 在字母表中的位置总是与 s[i+1] 相同或在 s[i+1] 之前。
例如:
输入:n=2
输出:15
解释:仅由元音组成的 15 个字典序字符串为
[“aa”,“ae”,“ai”,“ao”,“au”,“ee”,“ei”,“eo”,“eu”,“ii”,“io”,“iu”,“oo”,“ou”,“uu”]
注意,“ea” 不是符合题意的字符串,因为 ‘e’ 在字母表中的位置比 ‘a’ 靠后
这道题目来自力扣,
原题链接:https://leetcode-cn.com/problems/count-sorted-vowel-strings/
回溯算法
显然,这道题目最直接的思路就是使用回溯算法,这道题也是一道很标准的回溯算法题,难度不大。
直接上代码:
function countVowelStrings(n: number): number {const map = ['a', 'e', 'i', 'o', 'u'];//const res = [];let count = 0;// index用于记录下一轮回溯的开始位置,list用于保存当前回溯的数据状态const dfs = (index: number, list: string[]) => {if (list.length === n) {count++;// res.push(list.join(''));return;}for (let i = index; i < map.length; i++) {list.push(map[i]);dfs(i, list);list.pop();}}dfs(0, []);return count;
};
使用回溯算法的优势是可以把每一种组合的具体结果都记录下来(即代码中所注释掉的code),
但是由于我们不需要具体的结果只需要总共的结果数,并且使用回溯的时间复杂度高达O(2n),
所以我们考虑是否能将算法进行进一步优化。
不难发现,f(n)的结果是与其子问题f(n-1)的结果有直接关联,所以接下来我们使用动态规划来解决此问题。
动态规划
创建一个二维dp,行代表元音数组,列代表组合字符串的长度,
那么dp[i][j]表示以s[j]元音字母开头长度为i的组合总数。
以n=3为例可得到如下的二维数组表:
/*
* a e i o u sum
* 1 1 1 1 1 1 5
* 2 5 4 3 2 1 15
* 3 15 10 6 3 1 35
*/
从表中,我们不难得出其状态转移方程:dp[i][j] = dp[i-1][j]+dp[i][j+1]。
代码如下:
function countVowelStrings(n: number): number {const dp = new Array(n).fill(0).map(() => new Array(5).fill(1));for (let i = 1; i < n; i++) {//由于状态转移方程的特性,所以此处采取倒序遍历for (let j = 3; j >= 0; j--) {dp[i][j] = dp[i - 1][j] + dp[i][j + 1];}}let sum = 0;for (let j = 0; j < 5; j++) {sum += dp[n - 1][j];}return sum;
};
``
此算法的时间复杂度为O(n)(因为元音数组的长度是已知的)。
到此,O(n)的时间复杂度还能再进一步优化吗?答案是当然可以的,因为数学,yyds!
数学(盒子放球模型)
长度为5的元音数组组合成长度为n的字符串种数转换为数学问题就等价于有n个小球放到5个盒子里(盒子可以为空),有多少方式?
首先我解释一下为何能如此等价,因为题目条件的限制使得每一种确定的放置方式能且仅能得到一种组合,比如一个’a’一个’e’两个’o’,它只能得到一个结果,那就是’aeoo’。
然后我们来解决数学问题,这是一道高中的经典排列组合问题(组合数学里面也有),先看它的一般问题:
n个小球放到m个盒子里(盒子可以为空),有多少方式?
由于盒子可以为空,貌似不容易解决,我们可以尝试将其进行等价变形处理:
n+m个小球放到m个盒子里(每个盒子至少有一个小球),有多少方式?
第二种方式其实就是增加m个小球然后给每个盒子都默认放置一个小球即可。
那么如何处理第二种问题呢?接下来就要引入数学的神奇手法–“挡板”,我尝试用另外一种更容易理解的方式来描述这个“挡板”。
m个盒子有m-1个间隙,n+m个小球含有n+m-1个间隙,将n+m个小球放到m个盒子相当于在小球的n+m-1个间隙中选取m-1个间隙来放置挡板,进而将小球分成m个部分也就是m个盒子,那么总共就有C(n + m - 1, m - 1)种方式。回到本题,那么答案就是C(n + 4, 4)。
所以使用此种方式,那么只需要一行代码:
function countVowelStrings(n: number): number {return (n + 4) * (n + 3) * (n + 2) * (n + 1) / 24;
};
此算法时间复杂度为O(1)!
结语
终究,数学才是最强大的算法源泉,没有之一!
统计字典序元音字符串的数目(一题三解)相关推荐
- Leetcode.1641 统计字典序元音字符串的数目
题目链接 Leetcode.1641 统计字典序元音字符串的数目 Rating : 1519 题目描述 给你一个整数 n,请返回长度为 n.仅由元音 (a, e, i, o, u)组成且按 字典序排列 ...
- LeetCode 1641. 统计字典序元音字符串的数目(DP)
文章目录 1. 题目 2. 解题 1. 题目 给你一个整数 n,请返回长度为 n .仅由元音 (a, e, i, o, u) 组成且按 字典序排列 的字符串数量. 字符串 s 按 字典序排列 需要满足 ...
- C++描述 LeetCode 5677. 统计同构子字符串的数目
C++描述 LeetCode 5677. 统计同构子字符串的数目 大家好,我叫亓官劼(qí guān jié ),在CSDN中记录学习的点滴历程,时光荏苒,未来可期,加油~博主目前仅在CSDN中写 ...
- [M数学] lc1759. 统计同构子字符串的数目(数学+等差求和)
文章目录 1. 题目来源 2. 题目解析 1. 题目来源 链接:1759. 统计同构子字符串的数目 2. 题目解析 分析题目,连续字符串对答案的贡献实际上是 等差数列求和 即可,采用双指针求出连续字符 ...
- LeetCode 1759. 统计同构子字符串的数目
文章目录 1. 题目 2. 解题 1. 题目 给你一个字符串 s ,返回 s 中 同构子字符串 的数目. 由于答案可能很大,只需返回对 10^9 + 7 取余 后的结果. 同构字符串 的定义为:如果一 ...
- Python一题三解:查找字符串中每个字符的首次出现
题目要求: 查找字符串中每个字符的首次出现.给定一个任意字符串,要求得到一个新字符串,重复字符只保留一个,并且新字符串中的字符保持在原字符串中首次出现的先后顺序.例如,abcdaaabe处理后应得到a ...
- Python趣题三解:根据线索计算违章逃逸的车牌号
封面图片:<Python程序设计实验指导书>(ISBN:9787302525790),董付国,清华大学出版社 图书详情(京东): 本书81个实验项目可与董付国老师的<Python程序 ...
- Python一题三解:查找总分等于特定值的同学成绩
问题描述:已知一些同学几门课程的成绩,要求查找总分等于某个特定值的成绩情况. 参考代码: 运行结果: 温馨提示 进入公众号,通过菜单"最新资源"==>"历史文章&q ...
- python字典统计排序 统计各省份大学数量_1641统计字典排序元音字符串的数量(递归,递归),数目,递推...
1. 问题描述: 给你一个整数 n,请返回长度为 n .仅由元音 (a, e, i, o, u) 组成且按 字典序排列的字符串数量.字符串 s 按字典序排列需要满足:对于所有有效的 i,s[i] 在字 ...
最新文章
- 省钱之道--图解域域树域林根域的含义
- mysql 5.6 并行复制_MySQL 5.6并行复制架构
- ubuntu时钟不显示的解决方法
- CSS Sprites图片合并
- modelsim6.5b安装和仿真bug
- MySQL工作笔记-使用rand生成随机数及用随机数填充记录
- sql注入空格被过滤_网站渗透:SQL注入与WAF绕过思路分享
- python效率低为什么_为什么我的工作效率降低了?
- 中山大学本科偏微分方程试题
- 计算机管理 服务在哪,信息服务,教您哪里打开Internet信息服务(IIS)管理器
- google 常用的技术搜索关键词
- Elasticsearch(ES)入门,这一篇就够了
- 思维模型丨看先辈是如何学习的?
- mysql计算订单总金额_【写SQL语句】按照用户统计对应订单数和订单总金额?
- php医院预约挂号系统
- c++如何批量修改文件后缀名
- 如何设计安全可靠的开放接口---对请求参加密保护
- 自定义view - 收藏集 - 掘金
- 拼音反查(转自大富翁)
- 商业承兑汇票的相关概念