当前位置: 首页 > news >正文

leetcode_1742 盒子中小球的最大数量

1. 题意

给定一个数字范围,把每个数根据数位和放到相应的盒子中;求有最多数字的盒子编号。

2. 题解

这题比较简单,但有较多的解法。

2.1 哈希表

由于最大数为 100000 100000 100000,因此最大的数位和为 45 45 45。我们只需要开一个大小 46 46 46的更加方便,然后遍历这个范围,计算数位和,相应表项增加,最后求一个最大值就好了。

class Solution {
public:

    int countBalls(int lowLimit, int highLimit) {
        

    auto digitSum = [](int v) {
    int ans = 0;
        while (v) {
            ans += v % 10;
            v /= 10;
        }
        return ans;
    };

        vector<int> hs(46, 0);
        for (int i = lowLimit;i <= highLimit;i++) {
            hs[digitSum(i)]++;
        }


        return *max_element(hs.begin(), hs.end());
    }
};
2.2 前缀和

数据范围为 1 − 100000 1-100000 1100000,可以预处理出前 k k k个数每个数位和的状态,对于范围 [ a , b ] [a,b] [a,b]的 数位和就可以由 m e m [ b ] − m e m [ a − 1 ] mem[b] -mem[a-1] mem[b]mem[a1]得到。

class Solution {
public:

    int countBalls(int lowLimit, int highLimit) {
        
    array<array<int,46>, 100001> mem{};
    auto digitSum = [](int v) {
    int ans = 0;
        while (v) {
            ans += v % 10;
            v /= 10;
        }
        return ans;
    };

    for (int i = 1;i <= 100000;i++) {
        mem[i] = mem[i - 1];
        mem[i][digitSum(i)]++;
    }


        int ans = 0;
        for (int i = 1; i <= 45;i++) {
            ans = max(ans, mem[highLimit][i] - mem[lowLimit - 1][i]);
        }


        return ans;
    }
};
2.3 数位dp

数位dp入门见数位dp。

这个题目的状态转移方程为
m = ⌊ lg ⁡ n ⌋ a m = ⌊ n / ( 1 0 m ) ⌋ d p [ m ] [ k ] = ∑ i = 0 min ⁡ { a m − 1 , k } d p [ 1 0 m − 1 ] [ k − i ] + d p [ m − a m 1 0 m ] [ k − a m ] m =\lfloor \lg n \rfloor \\ a_m =\lfloor n /(10^{m}) \rfloor \\ dp[m][k]=\sum_{i=0}^{\min\{a_{m}-1,k\}}dp[10^{m-1}][k-i]+dp[m-a_m10^{m}][k-a_{m}] m=lgnam=n/(10m)⌋dp[m][k]=i=0min{am1,k}dp[10m1][ki]+dp[mam10m][kam]

我们可以预先求出 d p [ 1 0 d − 1 ] [ k ] dp[10^{d}-1][k] dp[10d1][k]

d p [ 1 0 d − 1 ] = T [ d ] dp[10^d-1]=T[d] dp[10d1]=T[d]

T [ d ] [ k ] = ∑ i = 0 min ⁡ { k , 9 } T [ d − 1 ] [ k − i ] T[d][k] = \sum_{i=0}^{\min \{k, 9\}}T[d-1][k-i] T[d][k]=i=0min{k,9}T[d1][ki]

下面是递归的代码,看之后能不能补一下递推的。

class Solution {
        public:
        static constexpr int MAXPOW = 5;
                static constexpr int BASE   = 10;
                static constexpr int MAXSUM = MAXPOW * (BASE - 1);
        int getRes(int v, int k, const std::array<std::array<int, MAXSUM + 1>, MAXPOW + 1> &dp) {


                    if ( v < 10) {
                        return v >= k ? 1 : 0;
                    }

                    int ans =  0;
        
                    int digitMost = 1;
                    int ts = BASE;
                    while (ts <= v) {
                        ts *= BASE;
                        digitMost++;
                    }
                    digitMost--;
                    int msb = v / (ts / BASE);
                    
                    int lm =  std::min(msb - 1, k) ;
                    for (int i = 0;i <= lm; i++)
                        ans += dp[digitMost][k - i];
                    
                    int ret = 0;
                    if (msb <= k) {
                        ret += getRes(v - msb * (ts / BASE), k - msb, dp);
                    }
        
                    
                    return ans + ret;
                }
            
            int countBalls(int lowLimit, int highLimit) {
        
                
                std::array<std::array<int,MAXSUM + 1>, MAXPOW + 1> dp{};
        
                for (int i = 0; i < BASE; i++)
                    dp[1][i] = 1;
        
                for (int i = 2;i <= MAXPOW; i++) {
                    for (int j = 0; j <= MAXSUM; ++j) {
        
                        int bd = std::min(BASE - 1, j);
                        for (int k = 0; k <= bd; ++k) {
                            dp[i][j] += dp[i - 1][j - k];
                        }
                    }
                }
                
        
                int ans = 0;
                for (int i = 1; i <= MAXSUM;i++) {

                    int nums = getRes(highLimit, i, dp) - getRes(lowLimit - 1, i, dp);
                
                    ans = std::max(ans, getRes(highLimit, i, dp) - getRes(lowLimit - 1, i, dp));
                }
        
        
                return ans;
            }
        };

Ref

03xf

相关文章:

  • Brave132编译指南 MacOS篇 - 构筑开发环境(二)
  • Leetcode1287:有序数组中出现次数超过25%的元素
  • Python学习心得Pycharm的程序调试
  • Unreal5从入门到精通之在编辑器中更新 UserWidgets
  • 从零复现R1之路[3/3]:一文速览Open R1——对DeepSeek R1训练流程前两个阶段的复现(SFT和GRPO训练)
  • 音视频入门基础:RTP专题(9)——FFmpeg接收RTP流的原理和内部实现
  • 51单片机-按键
  • 《仙台有树》追剧疑问与DeepSeek解答
  • LeetCode-633. 平方数之和
  • PHP图书借阅小程序
  • 当pcie设备变化时centos是否会修改网络设备的名称(AI回答)
  • GcExcel
  • Letsencrypt+certbot为域名免费配置ssl
  • 《Keras 3 :具有类似 U-Net 架构的图像分割》
  • 自定义RAG评估数据流
  • kotlin的onFailure: () -> Unit
  • 像素绽放PixelBloom(AiPPT.com) 联合创始人蒲世林:创新者的窘境就是新物种的机会
  • iOS 获取设备占用内存
  • C++17 数学特殊函数:探索标准库中的强大工具
  • 赶上AI的大潮:在VSCode中使用DeepSeek编程的极简方法
  • 幸福航空五一前三天航班取消:客服称目前是锁舱状态,无法确认何时恢复
  • 美乌总统梵蒂冈会谈,外交部:望有关各方继续通过对话谈判解决危机
  • 四川落马厅官周海琦受审,1000余人接受警示教育
  • 清华数字政府与治理研究院揭牌:服务数字政府建设需求
  • 京东美团开打,苦了商家?
  • 价格周报|猪价继续回暖:二次育肥热度仍存,对猪价仍有一定支撑