python解不等式组_LintCode Python解法

3.统计数字(Digit Count)

计算数字 k 在 0 到 n 中的出现的次数,k 可能是 0~9 的一个值。

首先是,惯用思维,2个循环解决,这样做的时间复杂度为O(n*2)

1 classSolution:2 """

3 @param k: An integer4 @param n: An integer5 @return: An integer denote the count of digit k in 1..n6 """

7 defdigitCounts(self, k, n):8 #write your code here

9 times =010

11 for i in range(n+1):12 item =str(i)13 while len(item) >0:14 if item[0:1] ==str(k):15 times += 1

16 item = item[1:]17 return times

提交成功后,看到讨论区有时间复杂度为O(log(n))的解法,搞懂思路后,终于自己实现了

本题求k出现的次数,其实可以等价于求k在各个数位上出现的次数之和

以n=3154为例,分情况讨论

设k所在数位为index(比如k在千位,index就是3;k在百位,index就是2)

设digit为k所在数位上,n对应的数值(比如k在千位,digit就是3;k在百位,digit就是1)

设k所在数位前的数为高位high,k所在数位后的数为低位low(比如k在百位,high就是3,low就是54;k在十位,high就是31,low就是4)

一、当k>digit时

1.k在个位:(000~314)k  high=315  index=0

共有315*1 = high*(10^index) = 315种可能

2.k在十位:(00~30)k(0~9)  high=31  index=1

共31*10 = high*(10^index) = 310种可能

3.k在百位:(0~2)k(00~99)  high=3  index=2

共3*100 = high*(10^index) = 300种可能

4.k在千位  high=0  index=3

共有0*1000 = high*(10^index) = 0种可能

所以,当k>digit时,k出现次数为high*(10^index)

二、当k=digit时

1.k在个位:(000~315)k  high=315  low=0  index=0

共有316 = 315*10^0+0+1 = high*(10^index)+low+1 = 316种可能

2.k在十位:(00~30)k(0~9)+31k(0~4)  high=31  low=4  index=1

共31*10+5 = 31*10^1+4+1 = high*(10^index)+low+1 = 315种可能

3.k在百位:(0~2)k(00~99)+3k(00~54)  high=3  low=54  index=2

共3*100+55 = 3*10^2+54+1 = high*(10^index)+low+1 = 355种可能

4.k在千位:k(000~154)  high=0  low=154  index=3

共0*1000+155 = 0*10^3+154+1 = high*(10^index)+low+1 = 155种可能

所以,当k>digit时,k出现次数为high*(10^index)+low+1

三、当k

1.k在个位:(000~315)k  high=315  index=0

共有316*1 = (315+1)*(10^0) = (hith+1)*(10^index) = 316种可能

2.k在十位:(00~31)k(0~9)  high=31  index=1

共32*10+10 = (31+1)*(10^1) = (hith+1)*(10^index) = 320种可能

3.k在百位:(0~3)k(00~99)  high=3  index=2

共4*(10^2) = (3+1)*(10^2) = (hith+1)*(10^index) = 400种可能

4.k在千位:k(000~999)  high=0  index=3

共1*(10^3) = (0+1)*(10^3) = (hith+1)*(10^index) = 1000种可能

所以,当k

四、当k=0时

由于没有0xxx,00xx,000x这种数字,

所以k=0时,在千位就比k等于其他数字少了1000次,在百位少100次,在十位少10次,

在个位时0000即为0,所以不比k等于其他数字时少

代码如下:

1 class Solution:

2 """

3 @param: : An integer

4 @param: : An integer

5 @return: An integer denote the count of digit k in 1..n

6 """

7

8 def digitCounts(self, k, n):

9 # k出现的次数

10 times = 0

11

12 quotient = n

13 # 将整数转为字符串后,利用 len() 判断 n 的位数

14 # i即为分析中的index

15 for i in range(len(str(n))):

16 # remainder 即为分析中的digit

17 remainder = quotient % 10

18 # 获得高位high

19 quotient = quotient // 10

20 power = pow(10, i)

21

22 if k > remainder:

23 times += quotient * power

24 elif k == remainder:

25 # 通过高位乘以10对应的(幂+1)

26 # 加上 digit乘以10对应的幂

27 # 获得与低位互补的新的高位

28 # 再用n减去新的高位,即可获得低位

29 new_quotient = quotient * power * 10 \

30 + remainder * power

31 times += (quotient * power \

32 + (n - new_quotient) \

33 + 1)

34 else:

35 times += (quotient + 1) * power

36

37 if k == 0:

38 # 当k不在个位时,k出现次数要减去10对应的幂

39 if power != 1:

40 times -= power

41

42 return times

4. 丑数II(ugly number ii)

设计一个算法,找出只含素因子2,3,5 的第 n 小的数。

符合条件的数如:1, 2, 3, 4, 5, 6, 8, 9, 10, 12...

解决本题的思路是,除了1以外,题目要求的丑数只含有2,3,5这3种质因子,所以后面的丑数都是前面的丑数乘以2,3,5得到的

原问题转化为求一个数列中,第n个丑数如何获得的问题

假设长度为n-1的丑数数列第一个数为uglys[1] = 1

设2*uglys[i] > uglys[n-1], 3*uglys[j] > uglys[n-1], 5*uglys[k] > uglys[n-1] (注意,这里的n-1表示第n-1个数,跟列表里的下标不一样)

如果i,j,k分别是满足上述不等式的最小整数,那么uglys[n] = min(2*uglys[i], 3*uglys[j], 5*uglys[k])

很显然,i,j,k大多时候是不同的,所以我们要设置3个下标来分别记录他们在数组中的位置

代码如下:

1 classSolution:2 """

3 @param n: An integer4 @return: return a integer as description.5 """

6 defnthUglyNumber(self, n):7 uglyNumers = [1]8

9 i2, i3, i5 =0, 0, 010 num2, num3, num5 = uglyNumers[i2] * 2, \11 uglyNumers[i3] * 3, \12 uglyNumers[i5] * 5

13 #虽然形式是双重循环

14 #但是里面的3个while每次最多各执行一次

15 #所以时间复杂度是O(n)

16 while len(uglyNumers) <17 while num2 uglynumers i2>

19 num2 = uglyNumers[i2] * 2

20 while num3 <= uglyNumers[-1]:21 i3 += 1

22 num3 = uglyNumers[i3] * 3

23 while num5 <= uglyNumers[-1]:24 i5 += 1

25 num5 = uglyNumers[i5] * 5

26 uglyNumers.append(min(num2, num3, num5))27 return uglyNumers[-1]

17>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值