zoukankan      html  css  js  c++  java
  • LeetCode902. Numbers At Most N Given Digit Set

    题目:

    We have a sorted set of digits D, a non-empty subset of {'1','2','3','4','5','6','7','8','9'}.  (Note that '0' is not included.)

    Now, we write numbers using these digits, using each digit as many times as we want.  For example, if D = {'1','3','5'}, we may write numbers such as '13', '551', '1351315'.

    Return the number of positive integers that can be written (using the digits of D) that are less than or equal to N.

     

    Example 1:

    Input: D = ["1","3","5","7"], N = 100
    Output: 20
    Explanation: 
    The 20 numbers that can be written are:
    1, 3, 5, 7, 11, 13, 15, 17, 31, 33, 35, 37, 51, 53, 55, 57, 71, 73, 75, 77.
    

    Example 2:

    Input: D = ["1","4","9"], N = 1000000000
    Output: 29523
    Explanation: 
    We can write 3 one digit numbers, 9 two digit numbers, 27 three digit numbers,
    81 four digit numbers, 243 five digit numbers, 729 six digit numbers,
    2187 seven digit numbers, 6561 eight digit numbers, and 19683 nine digit numbers.
    In total, this is 29523 integers that can be written using the digits of D.

     

    Note:

    1. D is a subset of digits '1'-'9' in sorted order.
    2. 1 <= N <= 10^9

    题意理解:

    给了你一个string数组D,和一个数字N。D中每个string包含的是一个数字字符。相当于就是D中包含了LD个一位数字,然后用这些数字进行组合,只要比N小就满足条件,问一共有多少种满足条件的组合可能。

    DP思想:

    对于D的组合,当组合的数字长度小于N的长度时,很好理解,就是D的size的i次幂相加,1 <= i < D;

    当组合的数字长度等于N的长度时,情况就有点复杂了,但是我们可以通过DP的思想来理解。

    即对于数字N从右往左扫描,如果对于一个扫描的点,再遍历D。

    1.如果D中的一个数字小于N中的当前值,那么当前位置的组合数就加上D长度的一个次幂,具体多少次幂,取决于N中当前位置,相当于就是 1XXX, 2abc 组合数就是D长度的3次幂。

    2.如果D中的一个数字等于N中的当前值,那么就加上前一个位置的组合数,相当于就是 1XXXX 和 1XXXX;组合数取决于后4位。

    3.如果D中的一个数字比N中的当前值大,其实不用处理,因为我们设定的DP数组初始值都是0;

    需要注意的就是DP数组要多开一个位置,存储最后一个值1,自己随便写一个就知道原因了。

    代码:

    class Solution {
    public:
        int atMostNGivenDigitSet(vector<string>& D, int N) {
            string s = to_string(N);
            int LD = D.size();
            int LN = s.size();
            int ans = 0;
            int DP[LN+1];
            memset(DP, 0, sizeof(DP));
            DP[LN] = 1;
            
            
            for(int i = LN-1; i >= 0; i--)
            {
                int nt = s[i] - '0';
                for(int j = 0; j < LD; j++)
                {
                    if(D[j][0] - '0' == nt)
                        DP[i] += DP[i+1];
                    else if(D[j][0] - '0' < nt)
                        DP[i] += pow(LD, LN - i - 1);
                }
                
            }
            
            for(int j = 1; j < LN; j++)
            {
                    
                    DP[0] += pow(LD, j);
            }
            
            return DP[0];
        }
    };
    

      

  • 相关阅读:
    Backbone.js 1.0.0源码架构分析(一)
    汤姆大叔的博客(深入理解JavaScript系列(2):揭秘命名函数表达式)
    求职之路(拿到百度、美团、趋势科技、华为offer)
    请大家注意这个网站www.haogongju.net
    后缀数组求最长重复子串
    2015阿里在线笔试题求两个字符串的最长子串
    剑指offer42:翻转单词顺序 VS 左旋转字符串(更高效、简便的解法)
    求和为s的连续正数序列
    数组中的逆序对
    求一串字符串的全排列和所有组合
  • 原文地址:https://www.cnblogs.com/dybala21/p/9668676.html
Copyright © 2011-2022 走看看