zoukankan      html  css  js  c++  java
  • 剑指Offer43:1~n整数中1出现的次数(数位DP)

     解题思路:数位DP。dp数组为dp[pos][sum]表示当前位以下还有pos个可变位并且当前位以及它的最高位出现了sum个1的dp值。因为数的取值为2^31所以,数组开dp[10][10]就够了。

    数位DP入门博客:

    https://www.luogu.com.cn/blog/virus2017/shuweidp#

    https://blog.csdn.net/qq_25957237/article/details/102877820

     1 class Solution:
     2     def dfs(self,pos,one_sum,limit):
     3         #如果剩余可变位为0,范围当前数所有的one_sum,即当前状态的之前位有多少个1了
     4         if pos==0:
     5             return one_sum
     6         #如果没有受限并且dp值被记录过了,直接返回状态值
     7         if not limit and self.dp[pos][one_sum]!=-1:
     8             return self.dp[pos][one_sum]
     9         up = 9
    10         if limit:
    11             up = self.nums[pos-1]
    12         ans =0
    13         for i in range(up+1):
    14             #状态转移方程:如果当前位是1,那么next_one_sum +=1
    15             if i==1:
    16                 nxt_one_sum = one_sum + 1
    17             else:
    18                 nxt_one_sum = one_sum
    19             #搜索下一位,下一个状态的limit的由当前limit控制并且当前的值真的到了当前位的限制值.
    20             #以365为例,搜索0??,1??,2??的limit都为false,只有当搜索3??的时候才继续为真.
    21             ans+= self.dfs(pos-1,nxt_one_sum, limit and i==self.nums[pos-1])
    22 
    23         if not limit:#如果没有限制,说明下次再访问dp[pos][one_sum]的状态是一样的,记忆化
    24             self.dp[pos][one_sum] = ans
    25         return ans
    26 
    27     def solve(self,n):
    28         self.nums = []
    29         while n:
    30             self.nums.append(n%10)
    31             n//=10
    32         #自高位向低位进行数位dp,因为从高位开始dp,因此limit为真
    33         return self.dfs(len(self.nums),0,True)
    34     def countDigitOne(self, n):
    35         # dp[pos][sum]表示当前位以下还有pos个可变位并且当前位以及它的最高位出现了sum个1的dp值
    36         #比如对于356这个数,0??的dp值应该与2??dp值一样为dp[2][0],但是与3??的dp值不同,因为3是最高位,受到limit的制约
    37         #它不能保存dp值,除非再添加一个limit的维度(dp[10][10][2]),1??的dp值为dp[2][1]
    38         self.dp = [[-1]*10 for _ in range(10)]
    39         cnt = self.solve(n)
    40         #print(self.dp[2][0])
    41         #print(self.dp[2][1])
    42         return cnt
    43 
    44 
    45 
    46 c = Solution()
    47 #n = 302
    48 z = c.countDigitOne(365)
    49 print(z)
  • 相关阅读:
    Azure ARM (2) 概览
    Azure SQL Database (22) 迁移部分数据到Azure Stretch Database
    Azure SQL Database (21) 将整张表都迁移到Azure Stretch Database里
    Azure SQL Database (20) 使用SQL Server 2016 Upgrade Advisor
    开源日志系统比较:scribe、chukwa、kafka、flume
    大型互联网架构概述
    可扩展Web架构与分布式系统
    linux TOP命令各参数详解【转载】
    MongoDB社区版本和企业版本差别
    基于Geoserver的业务分析(笔记)
  • 原文地址:https://www.cnblogs.com/ISGuXing/p/14601039.html
Copyright © 2011-2022 走看看