LeetCode357. Count Numbers with Unique Digits题解

来源:互联网 发布:农村淘宝如何盈利 编辑:程序博客网 时间:2024/05/17 05:10

1. 题目描述

Given a non-negative integer n, count all numbers with unique digits, x, where 0 ≤ x < 10^(n).
【翻译过来】:给出一个非负数n,需要我们计算从0-10^(n)这些数中有多少个数是完全不同的,即这个数的各个位的数字都是不同的。

2. 样例

n = 2;output: 91, exclude [11, 22, 33, 44, 55, 66, 77, 88, 99]

3. 分析

乍看一下,题目很简单,我们只要找到这其中的各个位不重复的数字就行了,于是最开始我用马上能想到的方法。

3.1. 方案1

利用n计算出从0-10^(n)一共有多少个数,作为外层循环,在其内部进行遍历每个数,判断每个数是否位unique digit。判断的算法:很简单的mod 10取余数的方法,判断mod 10后的余数和除以10之后是否相等,相等则说明有重复的,返回false。
事实证明:思路正确,但是判断算法出错,因为我的算法只是考虑了相邻不重复的情况,即只可以判断:1223这样的情况,如果是1232的话就无法给出正确结果。
如下图提交结果所示:我的计算结果比正确答案多出了很多,这就说明有些应当判断为false的我的程序判断错了。
【错误的源码】:

bool isUniqueDigit(int number) {        while(number > 0) {            int temp = number % 10;            number /= 10;            if (temp == number) {                return false;            }        }        return true;    }int countNumbersWithUniqueDigits(int n) {    unsigned long side = 1;    int i;    for (i = 0; i < n; i++) {        side *= 10;    }    unsigned long counter = 0;    for (int j = 0; j < (int)side; j++) {        if (isUniqueDigit(j) == true) {            counter++;        }    }    return counter;}

这里写图片描述

3.2. 方案2

以上方案错在了判断是否为unique digit的函数上面,我修改了函数,在该函数下开设了一个int store[10]的数组,模仿hash用来存储已经得到的某一位的值,如果查找存储过程中出现了冲突,则证明有重复元素。得到的结果虽然正确,但是超时了!!!
这就逼的我不得不另想算法。
这里写图片描述
【超时的代码】:

bool isUniqueDigit(int number) {    int store[10];    for (int i = 0; i < 10; i++) {        store[i] = -1;    }    while(number > 0) {        int temp = number % 10;        if (store[temp] == -1) {            store[temp] = 1;        }        else {            return false;        }        number /= 10;    }    return true;}

3.3. 方案3

观察到n就是代表了范围里面所有数字的最大位数,例如:n=3的时候,该范围下的unique digit最大是3位的(如123),最小是1位的。
并且每位数字可以使用排列组合的数学方法求解:

  • 最高位不是0:最高位有9种可能(1-9),第二位有9种可能(1-9里面排除和最高位相同的那个数字再加上0),第三位有8种可能(1-9里面排除和最高位相同的那个数字,排除和第二位相同的数字)以此类推……
  • 最高位是0:最高位确定是0了,其实计算的就是n-1时候的情况(如098,097,009,008)以此类推……
  • 返回这两种情况之和即可;
    这里写图片描述

4. 源码

【正确的源码】:

int countNumbersWithUniqueDigits(int n) {    int counterNot0 = 9;    int counter0 = 1;    if (n == 0) {        return 1;    }    /* 只有1位,即0-9,有10个数 */    else if (n == 1) {        return 10;    }    /* 第一个数不为0 */    for (int i = 2; i <= n; i++) {        counterNot0 *= (10-i+1);    }    /* 第一个数为0 */    counter0 *= countNumbersWithUniqueDigits(n-1);    return counterNot0 + counter0;}

5. 心得

普通的暴力算法因为超时而无法使用,很多时候我们可以根据提交的报错提示从而判断自己代码出现的问题类型。

原创粉丝点击