我的第一版解法 回溯法
int sum = 0;
bool isUniqueDigit(int num) {
if (num<10) return true;
int tmp = num % 10;
num /= 10;
while(num) {
if(tmp == num % 10) return false;
num /= 10;
}
return true;
}
void digui(int n,int num) {
if (n == 0) return;
n--;
for (int i = 0; i < 10 ;i++) {
if (isUniqueDigit(num + i)) {
sum++;
if (num + i != 0) digui(n,(num + i) * 10);
}
}
}
int countNumbersWithUniqueDigits(int n) {
if (n == 0) return 1;
digui(n,0);
return sum;
}
用了递归,用数字连接的方式回溯,AC了,但是400ms,很慢。
后来看了hint,发现可以用一个变量记录一下当前数字是否出现过,就不用每次都去判断这个数字是不是uniqueDigit了。
int sum = 0;
bool visit[10] = {false};
void digui(int n,int num) {
if (n == 0) return;
n--;
for (int i = 0; i < 10 ;i++) {
if (!visit[i]) {
sum++;
visit[i] = true;
if (num + i != 0) digui(n,(num + i) * 10);
visit[i] = false;
}
}
}
int countNumbersWithUniqueDigits(int n) {
if (n == 0) return 1;
digui(n,0);
return sum;
}
这样修改完,时间82ms,已经是第二梯队很快的一列的,还能优化,*10那块就不需要了,但是要对0做特殊处理,用*10也行。
最快的方案是总结规律,n为0时是1,n为1时是10,n为2时是10 + 9 * 9 。。。。
也算是动态规划了。
代码就不贴了