https://leetcode.com/problems/numbers-with-repeated-digits/
与leetcode_357. Count Numbers with Unique Digits有一些相似的地方。
给定N,计算小于等于N且至少有一个重复数位的数的数目。
可转化为计算小于等于N且所有数位不相同的数的数目。且可分为两部分,
- 位数与N相同且小于等于N且所有数位不相同的数的数目;
- 位数小于N且所有数位不相同的数的数目。
难点在于第1部分。
解法一:
使用dfs计算第一部分。时间上开销相对较大
class Solution{ public: int res_=0, numofdigist_=0; bool flag[10]; int digists[10];
void dfs(int numofdigist, int digist, bool smaller){ if(numofdigist == 1){ if(!smaller){ for(int i=0; i<=digist; i++) if(flag[i]==0) res_++; } else{ for(int i=0; i<=9; i++) if(flag[i]==0) res_++; } return; } for(int i=0; i<=9; i++){ if(i==0&&numofdigist==numofdigist_) continue; if(i>digist && smaller==0) break; if(flag[i]==0){ flag[i]=1; if(!smaller&&i<digist) dfs(numofdigist-1, digists[numofdigist-2], 1); else if(!smaller&&i==digist) dfs(numofdigist-1, digists[numofdigist-2], 0); else if(smaller) dfs(numofdigist-1, digists[numofdigist-2], 1); flag[i]=0; } } } int numDupDigitsAtMostN(int N){ if(N<=10) return 0; int n=N; int weight=10; while(N>0){ digists[numofdigist_++] = N%10; N/=10; } memset(flag, 0 , sizeof(flag)); dfs(numofdigist_, digists[numofdigist_-1], 0); for(int i=1;i<=numofdigist_-1;i++){ int tmp=9; for(int j=1;j<i;j++) tmp *= 9-j+1; res_+=tmp; } return n-res_; } };
解法二:
从最高位开始,计算当前i位相同情况下小于等于N且所有数位不相同的数的数目。
class Solution{ public: int res_=0, numofdigist_=0; bool flag[10]; int digists[10];
int calc(int num, int wei){ //计算还剩num个数没用,还剩wei位有多少种情况 int res=1; for(int i=0; i<wei; i++) res *= num-i; return res; }
int numDupDigitsAtMostN(int N){ if(N<=10) return 0; N++; //计算小于N的数目,更方便处理 int n=N; int weight=10; while(N>0){ //计算出N的位数和每一位的数值 digists[numofdigist_++] = N%10; N/=10; }
//计算第1部分 memset(flag,0,sizeof(flag)); res_ = (digists[numofdigist_-1]-1)*calc(9,numofdigist_-1);//第1位不能为0 flag[digists[numofdigist_-1]]=1; for(int i=numofdigist_-2; i>=0; i--){ for(int j=0; j<digists[i]; j++) if(flag[j]==0) res_ += calc(9-numofdigist_+i+1, i); if(flag[digists[i]]==1) break; flag[digists[i]]=1; }
//计算第2部分 for(int i=1; i<=numofdigist_-1; i++){ int tmp=9; for(int j=1; j<i; j++) tmp *= 9-j+1; res_+=tmp; } return n-1-res_; }