1到n中1出现的个数

offer39的要求是,求1-n的整数中1出现的次数,比如input25,那么1在1,10-19,21中出现了1+1+10+1(11出现了两个1)=13次

语法糖

俗话说得好,有count不count猪头三。

# offer39-solution 1
def count_1_nums(self, n):count = 0for i in range(1,n+1):count = count + str(i).count('1')return count

递归

其实我一开始在想这是个数学问题,怎么就和递归扯上关系了。
但是仔细想想,我们可以用 f ( n ) f(n) f(n)代表1~n这n个整数的十进制表示中1出现的次数,将n拆分为两部分,最高一位的数字top和其他位的数字other,分别判断情况后将结果相加。
举一个具体的例子吧:1995,看成top=1,other=995,单位 p o w = 1 0 3 pow=10^3 pow=103
那么1-999中的1的个数就是 f ( p o w − 1 ) f(pow-1) f(pow−1)
千位上是1的个数是 995 + 1 = o t h e r + 1 995+1=other+1 995+1=other+1
其它位是1的个数就是 f ( o t h e r ) f(other) f(other)
1的总数就是上述之和

可以看到,由于我们还分了千位是否1的判别,所以还要考虑千位不是1的例子:5678。对于5678而言:
1~999这个范围1的个数是 f ( p o w − 1 ) f(pow-1) f(pow−1)
1000~1999中千位上是1的个数是pow,其他位是1的个数即是999中出现1的个数,也就是 f ( p o w − 1 ) f(pow-1) f(pow−1)
2000-4999中1的个数是 3 f ( p o w − 1 ) 3f(pow-1) 3f(pow−1)
5000-5678中1的个数是 f ( o t h e r ) f(other) f(other)
1的总数就是上述之和。

拆分完以后,递归就不难写了。

# offer39-solution 2
class Solution:
def count_1_nums_Digui(self, n):l = len(str(n))sum = 0while(True):top = n // (10 ** (l-1))if l == 1:if top == 0:return 0else:return 1other = n % (10 ** (l-1))q = 10 ** (l - 1) - 1if top == 1:sum = sum + (other+1) + Solution().count_1_nums_Digui(other) + Solution().count_1_nums_Digui(q)else:sum = sum + 10**(l-1) + Solution().count_1_nums_Digui(other) + top * Solution().count_1_nums_Digui(q)return sum

编程之美

接下来这里仅供参考。我虽然读懂了《编程之美》在说什么,也算是看懂了代码。但是我绝对难以想出如此这般的方法,只能说突出一个离谱。

① 如果百位上数字为0,百位上可能出现1的次数由更高位决定。比如:12013,则可以知道百位出现1的情况可能是:100-199,1100-1199,2100-2199,……11100-11199,一共1200个。可以看出是由更高位数字(12)决定,并且等于更高位数字(12)乘以 当前位数(100)。

② 如果百位上数字为1,百位上可能出现1的次数不仅受更高位影响还受低位影响。比如:12113,则可以知道百位受高位影响出现的情况是:100-199,1100-1199,2100-2199,……11100-11199,一共1200个。和上面情况一样,并且等于更高位数字(12)乘以 当前位数(100)。但同时它还受低位影响,百位出现1的情况是:12100~12113,一共14个,等于低位数字(13)+1。

③ 如果百位上数字大于1(2-9),则百位上出现1的情况仅由更高位决定,比如12213,则百位出现1的情况是:100-199,1100-1199,2100-2199,……11100-11199,12100~12199,一共有1300个,并且等于更高位数字+1(12+1)乘以当前位数(100)。

如此这般:

# offer39-solution 3
def count_1_nums(n):count, m = 0, 1while m <= n:count += (n // m + 8) // 10 * m + (n // m % 10 == 1) * (n % m + 1)m *= 10return count

反正我不懂……

最大的礼物

offer42:在一个m×n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于0)。
你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格直到到达棋盘的右下角,现在给定一个棋盘及其上面的礼物,需要规划处一个路线,使得可以获得最大价值的礼物。

几乎是最典型的DP了,而且也很好写出递推式:
d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] ) + a [ i ] [ j ] dp[i][j]= max (dp[i-1][j], dp[i][j-1])+ a[i][j] dp[i][j]=max(dp[i−1][j],dp[i][j−1])+a[i][j]
剩下的都是为这条递推式服务的一些辅助。

# offer42-solution
class Solution:# 假设输入array为一维数组,行数为rows,列数为cols,要求输出为最大的那个数值def getMaxValue(self,array,rows,cols):if array == [] or rows <= 0 or cols <= 0:return 0maxValues = [[0 for i in range(cols)] for j in range(rows)] # 全是0的辅助矩阵for i in range(rows):for j in range(cols):  # 从上往下搜索left = 0up = 0if i > 0:# 如果行号大于0,说明它上面有数字up = maxValues[i - 1][j] # 那么up就为从上方来的路径的礼物值if j > 0:# 如果列号大于0,说明它左边有数字left = maxValues[i][j - 1] # left就为从上方来的路径的礼物值maxValues[i][j] = max(up, left) + array[i * cols + j] # 两条路中的最大者加当前值return maxValues[rows - 1][cols - 1]  # 输出右下角的值

丑数

offer44:丑数是指只包含质因子2、3和5的数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 我们认为:1是第一个丑数,要求按从小到大的顺序的第N个丑数。

同样可以写成DP,对每个丑数,乘以2,3,5,然后判断新的丑数的位置。可以考虑分别对质因子2,3,5制作三个队列进行出队入队,更为简洁的方法应该是写成一个队列,但是判断3次。

# offer44-solution
class Solution:def GetUglyNumber_Solution(self,index):if index <= 0:return 0res = [1]nextIndex = 1t2 = t3 = t5 = 0while nextIndex < index:min_val = min(res[t2]*2,res[t3]*3,res[t5]*5)# 对每个丑数,乘以2,3,5,然后判断新的丑数的位置res.append(min_val)while res[t2]*2 <= min_val:  # 如果乘出来的结果较小,则指标向前移动t2 += 1while res[t3]*3 <= min_val:t3 += 1while res[t5]*5 <= min_val:t5 += 1nextIndex += 1return res[index-1]

《剑指offer》394244、数学类三则:1-n中1出现的个数、最大的礼物、丑数相关推荐

  1. 剑指offer——面试题3:二维数组中的查找

    剑指offer--面试题3:二维数组中的查找 1.笨蛋方法 复杂度为O(n2)O(n^2)O(n2) class Solution { public:bool Find(int target, vec ...

  2. 剑指 Offer 05. 替换空格 三种方法

    剑指 Offer 05. 替换空格(点击立即答题) 请实现一个函数,把字符串 s 中的每个空格替换成"%20". 示例 1: 输入:s = "We are happy.& ...

  3. 《剑指offer》每日分享三道题- 2 day

    <剑指offer>系列第二弹,让我们用饱满的热情,迎接接下来的几道小题. >本系列分享的都是常规做法和全新思路的总结,各位可千万不要看着眼熟,而错过新颖的思路噻!!! 文章目录 1. ...

  4. 剑指offer第2版Python题解(更新中)

    O(n^2)排序 冒泡排序.插入排序与选择排序(Python)_NLP_victor的博客-CSDN博客 归并 归并排序(Python)_NLP_victor的博客-CSDN博客 快排 快速排序(Py ...

  5. 数组中其余的排除_[leetcode 剑指offer系列] 面试题04. 二维数组中的查找

    题目难度: 简单 原题链接 今天继续更新剑指 offer 系列, 这道题的优化空间非常大, 个人感觉很适合作为面试题, 值得一做. 大家在我的公众号"每日精选算法题"中的聊天框中回 ...

  6. 字符串(一) | 剑指 Offer 58 - II. 左旋转字符串、541. 反转字符串 II、剑指 Offer 05. 替换空格、151. 反转字符串中的单词

    剑指 Offer 58 - II. 左旋转字符串 把前k个字符移动到结尾 翻转前k个字符,翻转剩余字符 翻转整个字符串 class Solution { public:void reverse(str ...

  7. Suzy找到实习了吗Day 8 | 字符串开始啦 344. 反转字符串,541. 反转字符串 II,剑指 Offer 05. 替换空格,151. 反转字符串中的单词,左旋转字符串

    这里是目录 344. 反转字符串 题目 Solution 541. 反转字符串 II 题目 Solution(v1) Solution(v2) 剑指 Offer 05. 替换空格 做题记录 151. ...

  8. 剑指offer | 面试题53 - II. 0~n-1中缺失的数字

    转载本文章请标明作者和出处 本文出自<Darwin的程序空间> 本文题目和部分解题思路来源自<剑指offer>第二版 开始行动,你已经成功一半了,献给正在奋斗的我们 题目 一个 ...

  9. 剑指Offer - 面试题43. 1~n整数中1出现的次数(找规律+公式)

    1. 题目 输入一个整数 n ,求1-n这n个整数的十进制表示中1出现的次数. 例如,输入12,1-12这些整数中包含1 的数字有1.10.11和12,1一共出现了5次. 示例 1: 输入:n = 1 ...

最新文章

  1. mysql数据导入python_利用python将mysql中的数据导入excel
  2. 2013年第10周三低潮
  3. Java数组和Arrays类
  4. html:(24):内联式css和嵌入式css
  5. 程序员在互联网公司和行业软件公司工作,有什么区别?
  6. Currently, the Linux Mint team has 21 members
  7. iOS开发-UITableView常用方法
  8. 【主机】软件(程序)的运行机制
  9. TeleportUltra_1.65_PortableSoft离线浏览利器-扒网页神器
  10. 微信小程序后台服务器搭建
  11. SPEA多目标优化算法--测试case发电机发电量分配[转]
  12. Testlink 使用步骤
  13. 微信公众帐号第三方服务平台源码
  14. 转:【PAMI2018】ASTER_An Attentional Scene Text Recognizer with Flexible Rectification
  15. 返璞归真-删除文件默认打开方式
  16. JAVA stream流对集合进行替换修改
  17. 交易员怎样于牛市中基于KDJ进行选股
  18. 3, excel vba 获取表格里的单元格的值
  19. GEO数据挖掘全流程分析
  20. 【AI作画】使用stable-diffusion-webui搭建AI作画平台

热门文章

  1. 阿里云Ubuntu系统配置二级域名解决方案|Cion.
  2. iview 加载html文件,iview-admin开发文档
  3. java反编译工具_App安全检测实践基础——工具
  4. [k8s]gosu使用
  5. 字体 ttf 下载
  6. QuickRun-快速运行助手
  7. c语言浮点类型保留几位小数
  8. 快速掌握mongoDB(五)——通过mongofiles和C#驱动操作GridFS
  9. OKR团队绩效管理学习1
  10. Raspberry Pi构建Android示波器