LeetCode2376 统计特殊整数 - 排列组合

news/2024/9/21 7:06:03/
  • 题目链接
  • 发布于LeetCode的题解

思路

最开始尝试枚举,然后不出意外TLE了,于是开始尝试排列组合

解题过程

  1. 给定正整数 n ,设长度为 len ,从最高位到最低位的索引为 0~len-1

  2. 例如数字 65535,第 0~4 位分别为 6、5、5、3、5。用 a[0]~a[4] 表示。

  3. 我们要考虑从 1~65535 中所有的数有多少个特殊整数,可以把分成两部分

    • 1~9999

    • 10000~65535

  4. 其中对于 1~9999,我们又可以分为:

    • 1~9
    • 10~99
    • 100~999
    • 1000~9999
    1. 我们可以用 sum[i] 表示 i 位数(首位不为0)总共有多少个特殊整数,那么1~9999中的所有特殊数的个数就可以表示为: s u m [ 1 ] + s u m [ 2 ] + s u m [ 3 ] + s u m [ 4 ] sum[1]+sum[2]+sum[3]+sum[4] sum[1]+sum[2]+sum[3]+sum[4]
    2. 想要求出 sum[i],我们可以考虑从 0~9 这10个数字中选出 i 个不同的然后全排列,即 s u m [ i ] = A 10 i sum[i]=A_{10}^i sum[i]=A10i
  5. 对于10000~65535,我们可以分为:

    • 10000~59999
    • 60000~65535
  6. 其中,10000~59999 可以分为:10000~19999,……,50000~59999

    • 这里有 a[0]-1 个这种类型的区间,其中每个区间,可以看作10个数字中已经有一个被选了(放在最高位了),然后从剩下 9 个数字中选择不同的 len-1 个出来全排列,每一块的特殊数个数为 A 9 l e n − 1 A_9^{len-1} A9len1
  7. 最后是最为复杂的 60000~65535 这一部分。这里我引入两个标记——

    • 一个 flag 表示 n 的第 flag 位(0~len-1)第一次出现(从高位往低位看)重复的数字,那么前 flag 位固定后之后的计算就无效了。(举个例子,65535 的 flag=2,那么就不用再讨论 65500~65535 的所有数字了)如果 n 中不存在重复数字,我们就令 flag=len−1(循环边界)。

    • 第二个 f[11] 数组,f[i] 初始值为0,f[i]=1 表示数字 i 在 n 中出现了。我们特殊处理了 k=0 的最高位,然后从 k=1 枚举到flag位。

    • 枚举时第 k 位时,内循环 i:0~a[k]-1 这 a[k] 个数字。
      (注意这一位不能枚举到 a[k] !!!)

      a. 如果 f[i] == 1,那么第 k 位就不能取 i 这个数字,continue

      b. 否则,前面已经确定了 k+1 个数字,后面还剩 len-(k+1)=len-k-1 个位置待枚举,所以我们只能从 10-(k+1)=9-k 个数字中选择 len-k-1 个数字全排列

    1. C 9 − k l e n − k − 1 ∗ A l e n − k − 1 l e n − k − 1 = ( 9 − k ) ! ( 10 − l e n ) ! C_{9−k}^{len−k−1}∗A_{len−k−1}^{len−k−1}=\frac{(9−k)!}{(10−len)!} C9klenk1Alenk1lenk1=(10len)!(9k)!

    2. 最后记得令 f[a[k]]=1

    3. 如果 flag==len-1 ,此时有两种情况:

      1. 在最后一位出现重复;
      2. 没有重复。
      3. 所以我们特判一下:if(k==len-1 && !f[a[k]]) ans++;
      4. 因为最后一位必须枚举到 a[k](而前面的位不能枚举到 a[k])——思考为什么?

Tip:

可以先把简单的 0~99 部分直接输出:

if(n<=10) return n;
else if(n<=99) return n-n/11;

复杂度

  • 时间复杂度: O ( 1 ) O(1) O(1)

  • 空间复杂度: O ( 1 ) O(1) O(1)

Code

class Solution {
public:int countSpecialNumbers(int n) {if(n<=10) return n;else if(n<=99) return n-n/11;int fact[11];bool f[11],af[11];int len,ans=0,flag=20;memset(f,0,sizeof(f));memset(af,0,sizeof(af));memset(fact,0,sizeof(fact));vector<int> a;fact[0]=1;for(int i=1;i<=10;++i) fact[i]=i*fact[i-1];for(int i=0;n>0;i++){a.push_back(n%10);n/=10;}len=a.size();reverse(a.begin(),a.end());for(int i=0;i<len;++i){if(af[a[i]]){flag=i;break;}af[a[i]]=1;}flag=min(flag,len-1);for(int i=1;i<len;++i) ans+=9*fact[9]/fact[10-i];ans+=(a[0]-1)*fact[9]/fact[10-len];f[a[0]]=1;int k=1;while(k<=flag){for(int i=0;i<=a[k]-1;++i){if(f[i]) continue;ans+=fact[9-k]/fact[10-len];}if(k==len-1 && !f[a[k]]) ans++;f[a[k]]=1;k++;}return ans;}
};

http://www.ppmy.cn/news/1528293.html

相关文章

gin集成jaeger中间件实现链路追踪

1. 背景 新业务线带来新项目启动&#xff0c;需要改进原有项目的基础框架和组件能力&#xff0c;以提升后续开发和维护效率。项目搭建主要包括技术选型、框架搭建、基础服务搭建等。这其中就涉及到链路追踪的内容&#xff0c;结合其中的踩坑情况&#xff0c;用一篇文章来说明完…

RedisTemplate操作ZSet的API

文章目录 ⛄概述⛄常见命令有⛄RedisTemplate API❄️❄️ 向集合中插入元素&#xff0c;并设置分数❄️❄️向集合中插入多个元素,并设置分数❄️❄️按照排名先后(从小到大)打印指定区间内的元素, -1为打印全部❄️❄️获得指定元素的分数❄️❄️返回集合内的成员个数❄️❄…

设计模式-行为型模式-备忘录模式

1.备忘录模式定义 在不破坏封装的前提下&#xff0c;捕获一个对象的内部状态&#xff0c;并在该对象之外保存这个状态&#xff0c;这样可以在以后将对象恢复到原先保存的状态&#xff1b; 1.1 备忘录模式的优缺点 优点 提供了一种状态恢复的实现机制&#xff0c;使得用户可以…

清深海工院

一、英语问题 &#xff08;1&#xff09;海工院的英文是什么&#xff1f; Institute for Ocean Engineering &#xff08;2&#xff09;为什么选择海工院 Because Institute for Ocean Engineering has strong academic reputation and commitment to innovation. I have alw…

音视频入门基础:AAC专题(4)——ADTS格式的AAC裸流实例分析

音视频入门基础&#xff1a;AAC专题系列文章&#xff1a; 音视频入门基础&#xff1a;AAC专题&#xff08;1&#xff09;——AAC官方文档下载 音视频入门基础&#xff1a;AAC专题&#xff08;2&#xff09;——使用FFmpeg命令生成AAC裸流文件 音视频入门基础&#xff1a;AAC…

安克创新25届校招CATA北森测评:笔试攻略、真题题库、高分技巧

安克创新自适应能力CATA测评是该公司用于评估候选人认知能力的计算机自适应测评系统。该测评系统由北森题库提供支持&#xff0c;是国内唯一被国际计算机自适应测验协会(IACAT)收录的产品。测评主要评估以下几个维度&#xff1a; 言语能力&#xff1a;测试理解言语信息并基于这…

Mac 上,终端如何开启 proxy

前提 确保你的浏览器可以访问 google&#xff0c;就是得先有这个能力 步骤 查看网络的 http/https 还有 socks5 的 port配置 .zshrc 查看 port 点击 wifi 设置 以我的为例&#xff0c;我的 http/https 都是 7890&#xff0c; socks5 是 7891 查看代理的port 以我的软件…

开发易忽视的问题:InnoDB 行锁设计与实现

开发易忽视的问题&#xff1a;InnoDB 行锁设计与实现 存储模型和锁机制 存储结构 数据页&#xff1a; InnoDB 将表的数据存储在数据页中&#xff0c;每个页默认大小为 16KB。数据页中存储多个行记录&#xff0c;行记录按照主键顺序存放。 行格式&#xff1a; InnoDB 支持多种…