No of numbers less than a given number with no repeating digits

后端 未结 3 646
孤独总比滥情好
孤独总比滥情好 2021-01-06 11:11

How can we find the number of numbers less than a given number with no repeating digits in it?

For example the number of such numbers less than 100 is 90. (11, 22, 3

3条回答
  •  误落风尘
    2021-01-06 11:37

    You can consider two cases:

    • numbers shorter than the limit
    • numbers that that differ from the limit at some digit

    The count of d-digit numbers is 9*9*8*... = 9*9!/(9-d)! (the first digit may not be zero). The count of all numbers shorter than d is the count of 0-digit numbers + .. count of d-1-digit numbers. These sums may be precomputed (or even hard-coded).

    The count of d-digit numbers with f first digits given is (10-f)*...*(10-(d-1)) = (10-f)!/(10-d)!. You can precomupte the factorials as well.

    Pseudocode :

    To precompute fac:
      - fac = int[10];
      - fac[0] = 1;
      - for i in 1..10:
        - fac[i] = fac[i-1] * i;
    
    To precompute count_shorter:
      - cs = int[10];
      - cs[0] = 0;
      - cs[1] = 1; // if zero is allowed
      - for i in 1..10:
        - cs[i+1] = cs[i] + 9 * fac[9] / fac[10-i]
      - count_shorter = cs;
    
    To determine the count of numbers smaller than d:
      - sl = strlen(d)
      - if sl > 10
        - return count_shorter[11]
      - else
        - sum = 0
        account for shorter numbers:
        - sum += count_shorter[sl]
        account for same-length numbers; len=count of digits shared with the limit:
        - sum += 9* fac[9] / fac[10-sl];
        - for every len in 1..{sl-1}:
          count the unused digits less than d[len]; credits to @MvG for noting:
          - first_opts = d[len]-1;
          - for every i in 0..{len-1}:
            - if d[i] < d[len]
              - first_opts -= 1;
          - sum += first_opts * fac[9-len] / fac[10-sl] 
      - return sum
    

提交回复
热议问题