leetcode1012
# given number n, see whether n has repeated number
def has_repeated(n):
str_n = str(n)
return len(set(str_n)) != len(str_n) def permutation(n, k):
prod = 1
for i in range(k):
prod *= (n-i)
return prod # calculate number of non-repeated n-digit numbers
# note: the n-digit number can't start with 0
# i.e: n_digit_no_repeat(2) calculates the non-repeated
# numbers in range [10, 99] (inclusive)
def n_digit_no_repeat(n):
if n == 1:
return 9
else:
return 9 * permutation(9, n-1) class Solution(object):
def numDupDigitsAtMostN(self, N):
"""
:type N: int
:rtype: int
"""
N_str = str(N)
n_digit = len(N_str)
digits = list(map(int, N_str))
result = N - 1
prefix = 0
for i in range(1, n_digit):
result -= n_digit_no_repeat(i)
for i in range(n_digit):
# when we fix the most significant digit, it
# can't be zero
start = 0 if i else 1
for j in range(start, digits[i]):
if has_repeated(prefix * 10 + j):
continue
if i != n_digit-1:
result -= permutation(10-i-1, n_digit-1-i)
else:
# optmized from `result -= has_repeated(prefix*10+j)`
result -= 1
prefix = prefix*10 + digits[i]
return result + has_repeated(N)
以下分析过程是我自己的思路,和上面的代码思路不太一样,具体的实现过程稍后补充,先把我的分析过程记录下来。
1位(0~9)有0个
2位(10~99)有9个:11,22,33,44,55,66,77,88,99
3位(100~999)有252个
百位以1~9开头,因为对于100~199的情况和200~299的情况都是一样的,因此外层用9相乘。
以100~199为例:
1.首先要找的个位和十位一样的:00,,22,33,44,55,66,77,88,99,共10个。
2.找个位和百位一样的:01,,21,31,41,51,61,71,81,91,共10-1=9个。
3.找十位和百位一样的:10,,12,13,14,15,16,17,18,19,共10-1=9个。
但是2步中出现了数字11,3步中也出现了数字11,因此每一轮是10 + (10-1) + (10-1) = 28个,
因此外层9*28=252。
4位(1000~9999):有4464个
百位和千位单独考虑,是10~99:有9组包含重数字:11**,22**,33**,44**,55**,66**,77**,88**,99**。
这9组数字,因为前缀已经是重数,因此后面的**无论是多少都满足要求,这样就得到了9*100=900个。
接下来考虑10**~19**这10组,排除11**组之后,还剩9组。
分析如下:以10**为例:
1.首先找个位和十位一样的:00,,22,33,44,55,66,77,88,99,共10个。
2.找个位和百位0一样的:,,20,30,40,50,60,70,80,90,共10-1=9个。
3.找个位和千位1一样的:,,21,31,41,51,61,71,81,91,共10-1=9个。
4.找十位和百位0一样的:,,02,03,04,05,06,07,08,09,共10-2=8个。
5.找十位和千位1一样的:,,12,13,14,15,16,17,18,19,共10-2=8个。
可以看到有重复计算的数字,因此第2步的00在第1步已经出现过,因此第2步是9个;
第3步有1个重复数字,剩下9个。第4步有2个重复数字,剩下8个,第5步有2个重复数字,剩下8个。
根据上面的分析可以知道,每一组有10 + (10-1) + (10-1) + (10-2) + (10-2)=44个。
因此从1000~1999这1000个数字中,有9*44=396个。再加上11**的100个,这样就是496个。
那么同样的计算方式,可以知道2000~2999也是496,从1000~9999一共就是9*496=4464个。
1位:9*0=0
2位:9*1=9
3位:9*(10+(10-1)*1+(10-1)*1)=252
4位:9*(9*(10+(10-1)*2+(10-2)*2)+1*100)=4464
5位:9*(9*(8*(10+(10-1)*3+(10-3)*3)+2*100)+1*1000)=62784
6位:9*(9*(8*(7*(10+(10-1)*4+(10-4)*4)+3*100)+2*1000)+1*10000)=763920
7位:9*(9*(8*(7*(6*(10+(10-1)*5+(10-5)*5)+4*100)+3*1000)+2*10000)+1*100000)=8455680
8位:9*(9*(8*(7*(6*(5*(10+(10-1)*6+(10-6)*6)+5*100)+4*1000)+3*10000)+2*100000)+1*1000000)=88367040
9位:9*(9*(8*(7*(6*(5*(4*(10+(10-1)*7+(10-7)*7)+6*100)+5*1000)+4*10000)+3*100000)+2*1000000)+1*10000000)=896734080
10位:9*(9*(8*(7*(6*(5*(4*(3*(10+(10-1)*8+(10-8)*8)+7*100)+6*1000)+5*10000)+4*100000)+3*1000000)+2*10000000 )+1*100000000)=8996734080
10位以上,最内部的计算式子10+(10-1)*9+(10-9)*9=100,也就表示任意的数字都包含重复。
经过以上的分析,可以得到如下的递推公式:x表示数字的位数,例如x=3表示100~999之间的满足要求的数字个数(不含0~99之间的)
k=[9,8,7,6,5,4,3]
for x in range(3,11):
c = x - 4
he = (10+(10-1)*(x-2)+(10-(x-2))*(x-2))
p = 2
while c >= 0:
he = k[c] * he + (c+1) * pow(10,p)
c -= 1
p += 1
y = he * 9
print(y)
'''
252
4464
62784
763920
8455680
88367040
896734080
8996734080
'''
我尝试用这个思路来做一个完整的解决方案,如果能完成,我会代码补充上。如果做不出来,就算了吧,哈哈。
leetcode上面的hard题目,如果自己有思路就尝试着写一下,如果没有思路就学习别人的。
算法的能力的提升,是一个循序渐进的过程,急不得。
leetcode1012的更多相关文章
- [Swift]LeetCode1012. 至少有 1 位重复的数字 | Numbers With 1 Repeated Digit
Given a positive integer N, return the number of positive integers less than or equal to N that have ...
随机推荐
- PyQt—QTableWidget中的checkBox状态判断
一.QTableWidget实现checkBox效果 利用QTableWidgetItem对象的CheckState属性,既能显示QCheckBox,又能读取状态 table = QtGui.QTab ...
- vo和pojo
pojo直接描述数据库中的表和字段,一一对应 vo的话,可以多添加些属性,比如code对应的name,或者标识符等等 查询列表的时候也可以直接用vo,但是修改或添加记录必须是pojo QueryVo ...
- 服务容错保护断路器Hystrix之四:断路器监控(Hystrix Dashboard)-turbine集群监控
turbine 英[ˈtɜ:baɪn] n. 汽轮机; 涡轮机; 透平机; OK,上文我们看了一个监控单体应用的例子,在实际应用中,我们要监控的应用往往是一个集群,这个时候我们就得采取Turbine集 ...
- win下使用git-bash工具进行ssh免密登录服务器
1.ssh-keygen.exe 生成公钥私钥(.pub) 2.ssh-agent.exe bash 指定工具 3.ssh-add.exe **** 添加私钥 OK
- win7运行bat文件 一闪而过 解决 必须要将生成器放在C盘等没有中文的目录里
1.在*.bat所在的文件夹按住shift 键然后鼠标右键,选择“在此处打开命令窗口”, 2.输入bat文件名称然后回车 这样就不会自动消失(只在win7 x64 上尝试过)
- Mybatis 系列6-结合源码解析节点配置:objectFactory、databaseIdProvider、plugins、mappers
[Mybatis 系列10-结合源码解析mybatis 执行流程] [Mybatis 系列9-强大的动态sql 语句] [Mybatis 系列8-结合源码解析select.resultMap的用法] ...
- KPPW2.2 漏洞利用--文件下载
KPPW2.2 漏洞利用--文件下载 任意文件下载漏洞 环境搭建 1,集成环境简单方便,如wamp,phpstudy.... 2,KPPW v2.2源码一份(文末有分享)放到WWW目录下面 3,安装, ...
- C#的两种类据类型:值类型和引用类型
注:引用类型相等赋值是地址赋值,不是值赋值. 什么是值类型,什么是引用类型 概念:值类型直接存储其值,而引用类型存储对其值的引用.部署:托管堆上部署了所有引用类型. 引用类型:基类为Objcet 值类 ...
- is 和 == 区别,id() ,回顾编码,encode(),decode()
1. is 和 == 区别 id()函数 == 判断两边的值 is 判断内存地址例 s = "alex 是 大 xx"# abc = id(s) # 得到内存地址# print(a ...
- 利用Python实现FGO自动战斗脚本,再也不用爆肝啦~
Fate/Grand Order(非的肝不过欧的)作为索尼为了拯救自己不倒闭而开发的面向月厨的骗氪养成抽卡爆肝游戏,居然没有像隔壁<阴阳师>的自动战斗系统(看看别人现在都自带脚本了).毕竟 ...